Первый раздел урока: Таблица, или Основы порядка
Таблица — это одна из наглядных форм представления данных, которая состоит из нескольких строк и столбцов (например, таблица умножения).
Задачи урока
- Работа с компонентом StringGrid (текстовая таблица).
- Работа с компонентом UpDown (счётчик).
Выполнение упражнения
В этом упражнении вы напишете приложение «Квадрат функции», реализующее вычисление функции y(x) = x2, с табличным отображением значений аргумента и функции (рисунок 1). Приложение должно обладать следующими возможностями:
- задавать количество строк таблицы;
- предусматривать возможность ввода значения аргумента вручную.
Рисунок 1. Окно приложения
1. Дизайн приложения
- Расположите на форме компоненты, как показано на рисунке 2.
Для размещения таблицы на форме необходимо из категории Additional Палитры компонентов выбрать компонент StringGrid .
Также на форме разместите компонент UpDown , находящийся на вкладке Win32. Этот компонент является просто счетчиком.
Рисунок 2
Следующим, ещё незнакомым нам, элементом на форме является компонент Bevel (вкладка Additional). Этот компонент не имеет событий и предназначен только для внешнего оформления (на рисунке 2 два этих компонента расположены в правом нижнем углу).
- Поменяйте свойства компонентов (пока не трогая таблицу и компоненты Bevel) так, как показано на рисунке 3. Поменяйте заголовок формы на «Таблица».
Рисунок 3
Отметим, что кнопка «Случайно» будет использована во второй части урока.
- Выберите компоненты Bevel и присвойте свойству Shape (Фигура) значение TopLine (Верхняя линия), как показано на рисунке 4а. В результате вид фигур изменится с квадратов на линии. Разместите эти линии, как показано на рисунке 4б. После таких «украшений» приложение выглядит куда лучше.
а) б)
Рисунок 4
2. Оформление таблицы
- Выделите таблицу и переключитесь в окно Инспектор объектов. Свойства RowCount и ColCount служат для задания количества строк и столбцов таблицы (рисунок 5). Задайте их равным 2.
а) б)
Рисунок 5
- В момент добавления таблицы на форму у неё по умолчанию одна фиксированная строка (свойство FixedRows) и один фиксированный столбец (свойство FixedCols). Фиксированные строки и столбцы таблицы обозначены серым цветом. Фиксированными называются ячейки, которые нельзя выделить, и они остаются неподвижными при просмотре информации в таблице. На них можно только помещать поясняющие надписи.
В данном случае фиксированный столбец не нужен, поэтому обнулите свойство таблицы FixedCols (рисунок 6). Оставьте одну фиксированную строку.
Рисунок 6
- Теперь поменяйте свойство Align таблицы на alLeft, чтобы она «прилипла» к левой границе формы. Это позволит динамически изменять количество отображаемых строк таблицы при изменении размера формы.
- За цвет фиксированных ячеек отвечает свойство таблицы FixedColor. Задайте этот цвет как clAqua. В результате фиксированные ячейки окрасятся в цвет морской волны (рисунок 7).
Рисунок 7
- По умолчанию ширина всех колонок таблицы одинаковая и довольно большая. Задаёте размер первой колонки, где будут отображаться значения аргумента, как показано на рисунке 8.
Рисунок 8
- Высота строк таблицы задаётся свойством таблицы DefaulRowHeight, измените его значение на 18.
На этом закончим конструирование таблицы.
- Выделите компонент UpDown. Задайте у него свойство Min = 1, т. к. таблица будет состоять как минимум из одной рабочей строки. Также измените свойство Associate на EditRow. При этом счётчик «прилипнет» к однострочному редактору. И последний будет отображать свойство Position компонента UpDown.
- Задайте имена компонентов следующим образом:
Имя, которое
было |
Имя, на которое
необходимо изменить |
StringGrid1 | GridOut |
Edit1 | editRow |
UpDown1 | UpDown |
Button1 (Случайно) | buttonRND |
Button2 (Вычислить) | buttonCalc |
Button3 (Выход) |
buttonExit |
- Запустите приложение. К сожалению, пока можно только выбирать ячейки таблицы, без возможности их редактирования. Пощёлкайте на кнопках счётчика. Закройте приложение.
3. Редактирование ячеек таблицы
- Выделите таблицу и перейдите к окну Инспектор объектов. Найдите во вкладке Properties свойство Options и откройте список дополнительных свойств, нажав на крестик слева от свойства (рисунок 9а). Выберите значение True у появившегося свойства goEditing (Редактировать). Это свойство отвечает за возможность редактировать ячейки таблицы в работающем приложении.
а) б)
Рисунок 9
- Запустите приложение. Запишите произвольный текст в какую-либо ячейку таблицы (рисунок 9б). Ячейка становится активной для редактирования после двойного щелчка мыши на ней. Закройте приложение.
4. Обрабатываем основные события
- Напишите уже знакомый нам обработчик события OnClick для кнопки «Выход» (компонент ButtonExit).
- Напишите обработчик события OnClick для компонента UpDown, при нажатии на который изменяется число редактируемых строк:
procedure TForm1.UpDownClick(Sender: TObject; Button: TUDBtnType); begin // Задание числа строк GridOut.RowCount := UpDown.Position+1; end;
Листинг 1
Добавление цифры 1 связано с тем, что в однострочный редактор мы вводим количество редактируемых строк, а есть ещё одна строка — фиксированная.
5. Вычисляем функцию
- Напишите обработчик события OnClick для кнопки «Вычислить» (компонент ButtonCalc), при нажатии на которую результат вычисления функции y(x) будет заноситься в ячейки второго столбца таблицы:
procedure TForm1.ButtonCalcClick(Sender: TObject); var V,f:Integer; begin // -- Заполнение всех строк второго столбца таблицы результатом вычисления функции -- // Задаём цикл от 1 до количества строк For f:=1 to GridOut.RowCount do if GridOut.Cells[0,f]<>'' then begin // Проверяем, пустая ли строка? // Получаем числовое значение аргумента из ячейки с номером строки f V:= StrToInt( GridOut.Cells[0,f] ); // Помещаем результат во второй столбец, в ячейку с номером строки f GridOut.Cells[1,f]:=IntToStr( Sqr( V ) ) End Else // Если да, то выводим сообщение об ошибке GridOut.Cells[1,f]:='Ошибка'; end;
Листинг 2
Поясним код:
Для того чтобы во второй столбец записать значение функции от аргумента, находящегося в первом столбце, сначала необходимо из каждой строки первого столбца считать аргумент и преобразовать его в число (в листинге 2, выделено жёлтым). Потом это число возвести в квадрат, преобразовать в строку и передать её второму столбцу той же строки (в листинге 2, выделено зелёным), как показано на рисунке 10.
Рисунок 10
Очевидно, что для последовательного заполнения результатом вычисления второго столбца таблицы необходимо задать цикл по всем строкам (в листинге 2, выделено красным). Доступ к каждой отдельной ячейке осуществляется через свойство таблицы Cells [ x, y ], где x — это номер столбца, а y — номер строки. Нумерация строк и столбцов таблицы начинается с нуля.
Попутно проверяем значение ячеек первого столбца. Если ячейка пустая, то выводится сообщение «Ошибка» во втором столбце (в листинге 2, выделено голубым).
- Запустите приложение и проверьте его функциональность:
- установите 6 строк в таблице при помощи счётчика;
- заполните левый столбец произвольными числами;
- нажмите на кнопку «Вычислить». Второй столбец автоматически заполнится значениями функции с соответствующими аргументами, записанными вами в первом столбце таблицы (рисунок 11).
Рисунок 11. Окно приложения
Закройте приложение.
6. Коротко о главном
Компонент UpDown (вкладка Win32) является счетчиком.
Компонент Bevel (вкладка Additional) не содержит событий и используется только для внешнего оформления формы.
Компонент StringGrid ( вкладка Additional) — это таблица.
Свойства RowCount и ColCount задают число строк и столбцов таблицы.
Для доступа к ячейке таблицы используется свойство Cells, которое является двухмерным массивом всех ячеек таблицы (нумерация начинается с нуля).
Фиксированная строка в таблице не может быть выделена.
Пользователь может редактировать ячейки таблицы в работающем приложении, если свойство goEditing = True.
Второй раздел урока:Таблица, или Добавляем клавиатуру
В предыдущем разделе урока № 5 — Таблица, или Основы порядка мы создали приложение, реализующее вычисление функции y(x) = x2, с табличным отображением значений аргумента и функции, позволяющее:
- пользователю задавать количество строк таблицы;
- вручную вводить значение аргумента;
- получать результат вычисления функции.
Во втором разделе урока мы расширим функциональность приложения. Научимся задавать начальные параметры приложения при его запуске и обрабатывать события, происходящие при нажатии клавиш на клавиатуре.
Задачи урока
- Работа с компонентом StringGrid.
- Работа с компонентом UpDown.
- Установка начальных параметров приложения.
- Обработка событий с клавиатуры.
Выполнение упражнения
Приложение после выполнения второй части урока должно позволять:
- заполнять колонку аргумента случайными числами;
- автоматически вычислять значение функции в момент записи аргумента;
- отслеживать правильность ввода чисел в однострочный редактор.
На рисунке 1 показано окно приложения после выполнения второй части урока.
Рисунок 1. Окно приложения
1. Заполнение таблицы случайными числами
1. Откройте проект, созданный в предыдущем разделе.
2. Напишите обработчик события OnClick для кнопки «Случайно» (компонент ButtonRND), при нажатии на которую столбец аргументов будет заполняться случайными числами от –10 до 10:
procedure TForm1.ButtonRNDClick(Sender: TObject); var f:Integer; begin // -- Заполнение всех строк первого столбца таблицы случайными числами -- For f:=1 to GridOut.RowCount do // Заполняем первый столбец случайными числами от -10 до 10 GridOut.Cells[0,f] := IntToStr(Random(21)-10); // Вызываем процедуру OnClick кнопки “Вычислить” для вычисления значений функции ButtonCalcClick(Sender); end;
Поясним код:
Как и в предыдущем случае, мы организовали цикл по всем строкам таблицы (выделено жёлтым). Но только в этот раз заполняем элементы первого столбца.
Обратите внимание, что в конце обработчика события мы вызываем процедуру OnClick кнопки «Вычислить» для того, чтобы после заполнения столбца аргументов автоматически происходил расчёт значений функции.
3. Запустите приложение. Установите 6 строк в таблице при помощи счётчика. Далее нажмите кнопку «Случайно». Левый столбец заполнится случайными числами, а правый — значениями функции. Закройте приложение.
2. Начальные установки приложения
1. Остался один очень досадный факт. В фиксированных ячейках таблицы ничего не написано и пользователю непонятно, куда что вводить и где что будет отображаться. Таблица не позволяет на этапе конструирования (Design Time) заносить в её ячейки какие-либо значения. Если необходимо задать начальные значения таблицы или других компонентов, или переменных, то используют событие формы OnCreate (с английского «создать»). Это событие возникает в момент старта приложения (а точнее, после создания формы в памяти компьютера и до появления её на экране монитора).
Создайте обработчик события OnCreate для формы Form1. Для этого выполните двойной щелчок на свободном от компонентов месте формы, либо выберите форму в окне Дерево объектов, перейдите на вкладку Events и выполните двойной щелчок напротив события OnCreate (рисунок 2). В результате этих действий в окне программного кода появится процедура обработки события создания формы:
procedure TForm1.FormCreate(Sender: TObject); begin end;
Рисунок 2
2. Напишите в процедуре OnCreate следующий код:
procedure TForm1.FormCreate(Sender: TObject); begin // Задания заголовков в фиксированных областях таблицы GridOut.Cells[0,0]:='x'; GridOut.Cells[1,0]:='y(x)=x^2'; // Активизация генератора случайных чисел Randomize; // Задание числа строк в однострочном редакторе (через счётчик) UpDown.Position:=3; // Задание числа строк в таблице через вызов события OnClick на счётчике UpDownClick(Sender, btNext); end;
Поясним код:
Здесь мы задаём заголовки для столбцов (выделено жёлтым) и активируем генератор случайных чисел.
Далее мы выставляем значение счётчика (компонент UpDown), равное 3, и вызываем его событие OnClick для того, чтобы изменить число строк в таблице. Обратите внимание, что у этого события есть второй параметр, который определяет, на какую из кнопок переключателя нажал пользователь. Нам он не важен, и поэтому мы вписали константу btNext, говорящую о том, что была нажата кнопка «Вверх».
3. Запустите приложение. В фиксированных полях таблицы появились названия, и количество строк в таблице стало равняться трём. Закройте приложение.
3. Обработка событий с клавиатуры
1. Теперь немного усовершенствуем приложение. Чтобы при изменении содержимого однострочного редактора и нажатии на клавишу Enter сразу же менялось число строк таблицы, обработайте событие нажатия клавиши у компонента EditRow. Для этого выделите компонент EditRow, найдите событие OnKeyDown (нажать кнопку) и создайте для него обработчик (двойным щелчком, справа от события). Запишите в нём следующий код:
procedure TForm1.EditRowKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); Begin // Проверка нажатия на клавишу с кодом 13 (Enter) If Key=13 Then UpDownClick(Sender,btNext) end;
Данное событие возникает в момент нажатия клавиши в активном компоненте. Посмотрите на параметры, которые оно возвращает:
- Key типа Word — этот целочисленный параметр содержит код нажатой клавиши;
- Shift типа TShiftState — параметр, содержит информацию о нажатии дополнительных клавиш (Shift, Ctrl, Alt).
В процедуре обработки события мы проверяем условие нажатия клавиши Enter (её код — 13). Если она нажата, то вызываем процедуру, отвечающую за нажатие на счётчик.
2. Не совсем красиво смотрится то, что при удалении всех символов из однострочного редактора там ничего не остаётся. Хотя там постоянно должно быть какое-либо число больше ноля.
Запрограммируем ситуацию, чтобы при удалении всех символов из компонента EditRow в нём автоматически появлялась единица, которая выделена (чтобы введенная пользователем цифра её заменяла).
Для этого обратимся к другому событию, возникающему в момент отпускания клавиши — OnKeyUp (переводится как «отпустить кнопку»). Создайте процедуру для обработки этого события у всё того же компонентаEditRow и заполните его следующим кодом:
procedure TForm1.EditRowKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); Begin // Проверка, что в компоненте EditRow нет текста If EditRow.Text='' then begin // Если это так, то выставляем единицу EditRow.Text:='1'; // Выделяем «1» EditRow.SelStart:=0; EditRow.SelLength:=1; end; end;
Сначала мы проверяем, есть ли в однострочном редакторе текст (выделено жёлтым), и если его там нет, то записываем в него единицу (выделено зелёным). Далее обращаемся к свойствам SelStart и SelLength. Первое из них определяет начальный символ выделения, а второй — число выделенных символов (выделено голубым).
Но почему нельзя было написать этот код в обработчике события OnKeyDown? Дело в том, что это событие генерируется перед тем, как в однострочном редакторе произойдут изменения, связанные с нажатием какой-либо клавиши.
3. Из вышесказанного встаёт резонный вопрос: Почему нельзя автоматически отслеживать вводимые числа в таблицу и сразу же вычислять значения функции? Конечно же, можно! Для этого обработайте событие таблицы SetEditText следующим образом:
procedure TForm1.GridOutSetEditText(Sender: TObject; ACol, ARow: Integer; const Value: String);begin Begin ButtonCalcClick(Sender); end;
Это событие возникает каждый раз, когда происходит изменение содержимого в ячейке таблицы. И каждый раз мы вызываем событие OnClick кнопки ButtonCalc.
4. Но если вычисление значений функции и отображение результата в таблице происходят автоматически, то зачем нам нужна кнопка «Вычислить»? Правильно, не нужна. Измените у кнопки «Вычислить» значение свойства Visible на False. Это означает, что данный компонент не будет виден в процессе работы приложения.
Но почему мы её не удалили? Дело в том, что мы ссылаемся на эту процедуру из других обработчиков событий. Такой способ довольно распространенный, когда часто используемую процедуру помещают в обработчик события OnClick кнопки, чтобы к ней было легче перейти.
5. Запустите уже полностью готовое приложение. Удалите из однострочного редактора все символы и увидите, как автоматически программа вставит единицу, которая будет выделена.
Теперь пробуйте редактировать какую-нибудь ячейку первого столбца. Результат выдаётся мгновенно! Введите в однострочный редактор число 9 и нажмите клавишу Enter. Число строк изменилось.
Оказывается, таблица — это очень полезная и, главное, наглядная вещь!
4. Коротко о главном
- Событие таблицы SetEditText возникает при изменении содержимого в ячейке таблицы.
- Для того чтобы в программном коде вызвать обработчик события какого-либо компонента, необходимо записать его имя с его параметрами (ведь это обычная процедура).
- Для установки начальных параметров приложения используют событие OnCreate, возникающее в момент создания формы.
- Событие OnKeyDown возникает в момент нажатия на клавишу клавиатуры. Содержит параметры: Key типа Word — целочисленный параметр, содержит код нажатой клавиши; Shift типа TShiftState — параметр, который содержит информацию о нажатии дополнительных клавиш (Shift, Ctrl, Alt).
- Событие OnKeyUp возникает в момент отпускания клавиши клавиатуры. Параметры аналогичны событию OnKeyDown.
- Код клавиши Enter — 13.
- Начало выделения и число выделенных символов в компонентах работы со строками задаётся свойствами SelStart и SelLength. При этом выделенный текст содержится в свойстве SelText. Чтобы выделить весь текст, используется метод SelectAll.
- Часто используемую процедуру, на которую ссылаются из нескольких мест кода, обычно записывают в событие OnClick кнопки, которую делают невидимой на этапе RunTime.
5. Выполнение заданий
Особенности задания
Все однострочные редакторы, в которые вводятся целые числа, должны иметь присоединённый компонент UpDown.
Задания I уровня сложности
1. Модифицируйте созданное приложение так, чтобы колонка y(x) = x^2 была доступна только для чтения (т. е. её нельзя было редактировать). Максимальное генерируемое случайное число (целое) должно вводиться с помощью дополнительного компонента Edit.
Подсказка! Если переменной Key в процедуре OnKeyUp присвоить значение 0, то нажатая клавиша будет «блокироваться».
2. Создайте приложение с двумя таблицами и двумя компонентами Edit. В первом компоненте Edit задаётся число строк таблиц, а во втором вводится некоторое целое число. При нажатии на кнопку «Вычислить» вторая таблица заполняется теми же элементами, что и первая таблица, но умноженными на это число. Таблицы имеют один столбец, без фиксированных строк и столбцов.
3. Создайте приложение «Натуральный логарифм«, у которого таблица состоит из двух столбцов. В первый столбец заносятся значения переменной X в диапазоне от 0.1 до 5 с шагом 0.1, а во вторую — соответствующее значение ln(X). Заполнение должно быть автоматическое, в момент запуска приложения.
4. Создайте приложение, которое в момент его запуска заполняет таблицу 5×5 случайными числами от 10 до 40. Таблица не должна иметь фиксированных полей, не должна редактироваться, а при щелчке на какой-либо ячейке должна выделяться вся строка. Причём сумма чисел в выделенной строке должна отображаться в компоненте Label.
5. Создайте приложение с таблицей размером 4х6, тремя компонентами Edit и кнопкой «Внести». Первые два однострочных редактора задают координаты ячейки таблицы, а третий — содержимое ячейки. При нажатии на кнопку «Внести» в таблице с введенными координатами должно появляться содержимое третьего компонента Edit. Таблица не должна редактироваться.
6. Создайте приложение с двумя квадратными (одинаковое количество строк и столбцов) таблицами одинакового размера и двумя кнопками: «Случайно» и «Вычислить». При нажатии на кнопку «Случайно» первая таблица должна заполняться случайными числами от 100 до 1000. При нажатии на кнопку «Вычислить» вторая таблица должна показать элементы первой, но отражённые относительно главной диагонали таблицы, т. е. строки должны стать столбцами, а столбцы строками.
7. Создайте приложение с таблицей размерностью n х m, где n и m вводятся в однострочных редакторах. Таблица должна заполняться числами, начиная с 1, при нажатии на кнопку «Заполнить» следующим образом (например, для размерности 4х3):
1 4 7 10
2 5 8 11
3 6 9 12
8. Создайте приложение с таблицей размером 5х5 с возможностью редактирования. При нажатии на кнопку «Вычислить» программа рассчитывает сумму всех ячеек таблицы и заносит результат в центральную ячейку [3,3]. Если какая-либо ячейка пустая в момент вычисления, то в неё заносится 0.
9. Создайте приложение с двумя таблицами 4х4. Таблицы заполняются строчными латинскими буквами (по одной букве на ячейку) в момент запуска приложения. При нажатии на кнопку «Поменять» элементы таблиц меняются местами (т. е. все значения ячеек из первой таблицы «перемещаются» во вторую в том же порядке, а все значения ячеек из второй таблицы «перемещаются» в первую).
10. Создайте приложение с таблицей размером 7х3 с возможностью редактирования. При нажатии на кнопку «Ок» находится минимальный элемент в таблице, и это значение заносится в заголовок формы.
Задания II уровня сложности
1. Создайте приложение «Таблица умножения«, состоящее из компонента StringGrid, поля ввода Edit и кнопки «Вычислить». В компонент Edit заносится максимальное число строк и столбцов таблицы (по умолчанию — 10). При нажатии на кнопку «Вычислить» должно происходить заполнение таблицы. Таблица должна быть квадратной.
2. Создайте приложение «Успеваемость«, которое будет содержать таблицу 6х6. В фиксированных столбцах будут фамилии учеников, например, «Иванов«, «Петров«, «Сидоров» и т. д. (Последний столбец не заполняется), а в фиксированной первой строке — школьные предметы, например, «Математика«, «Русский язык«, «Физкультура» и т. д. В ячейки таблицы вводятся оценки (от 1 до 5). При нажатии на кнопку «Вычислить» заполняется последний столбец таблицы (пятый), который имеет название «Средний балл«.
3. Создайте приложение с таблицей размерностью n х m, где n и m вводятся в однострочных редакторах. Таблица должна заполняться случайными числами от –100 до 100 при нажатии на кнопку «Заполнить». При нажатии на кнопку «Вычислить» программа должна рассчитать среднее арифметическое всех элементов таблицы и перезаполнить исходную таблицу следующим образом: к каждому элементу таблицы прибавляется среднее арифметическое, если значение меньше 0; и вычитается, если значение больше 0. Если значение в ячейке равно 0, то изменений не происходят.