Автор работы: Пользователь скрыл имя, 26 Января 2013 в 14:13, лекция
Программирование баз данных - очень большой и серьезный раздел самого что ни на есть практического программирования. На предыдущем курсе "Введение в программирование на Delphi" мы лишь коснулись этой темы, затронули даже не верхушку айсберга под названием Базы Данных, а только его макушку. Между тем, многие программисты большую часть своего времени тратят именно на проектирование баз данных и разработку приложений, работающих с ними. Это неудивительно - в настоящее время каждая государственная организация, каждая фирма или крупная корпорация имеют рабочие места с к
Дважды нажимаем на верхнюю кнопку, и в обработчике пишем код:
//добавляем запись:
fDM.TipsT.Append;
//переводим фокус:
DBEdit1.SetFocus;
В коде обработки нижней кнопки просто закрываем окно:
Close;
Однако нам нужно убедиться, что если изменения в таблице были, и пользователь желает их сохранить, то они сохраняются. Поскольку мы не знаем точно, каким образом пользователь закроет это окно, придется для проверки сгенерировать событие onClose для формы:
{если изменения есть, спросим что с ними делать. если пользователь
не желает их сохранять,
отменяем изменения. иначе
if fDM.TipsT.Modified then
if Application.MessageBox('Данные изменены! Сохранить?',
'Внимание!', MB_YESNO+MB_ICONQUESTION) <> IDYES then
fDM.TipsT.Cancel
else fDM.TipsT.Post;
Далее переходим на главную форму, командой File -> Use Unit подключаем модуль MyTypes, дважды щелкаем по кнопке "Типы блюд" и в сгенерированном событии вызываем новый модуль:
fMyTypes.ShowModal;
Сохраните проект, скомпилируйте его и впишите 5-10 типов блюд, например, "Напитки", "Супы", "Салаты" и т.п. Это нам будет нужно для подстановочного поля. Если в поле автоинкремента у вас будут выходить нули, не обращайте внимания - после сохранения таблицы там окажутся правильные цифры. Вы сможете убедиться в этом, закрыв программу и загрузив ее еще раз.
Теперь займемся формой для редактирования основной таблицы. Командой File -> New -> Form или аналогичной кнопкой на панели инструментов создайте новую форму. В свойство Caption этой формы впишите "Редактирование блюда", в свойстве Name укажите fEditor, а модуль сохраните как Editor. Сразу же командой File -> Use Unit подключите к этой форме модуль данных DM. Форма будет выглядеть так:
Рис. 5.6. Форма редактора блюда
Как видно из рисунка, на форме присутствуют поясняющие компоненты Label, три компонента DBEdit, один DBLookupComboBox, один DBNavigator и кнопка BitBtn, в свойстве Kind которой выбрано значение bkClose.
Компонент DBLookupComboBox немного сложней остальных. Это подстановочный компонент. Из основной таблицы Food он будет брать целое число - значение поля FType. А из дочерней таблицы Tips этот компонент будет просматривать все значения поля TName. Когда пользователь выберет какой-нибудь тип блюда, целое число, соответствующее ключевому полю TKey, попадет в поле FType главной таблицы. Другими словами, у нас получилась связь один-ко-многим (многие блюда основной таблицы могут иметь одинаковый тип):
Рис. 5.7. Связь между таблицами
Выделите все компоненты, относящиеся к редактированию данных или перемещению по ним (начинающиеся на DB…), и в их свойстве DataSource выберите fDM.FoodDS. Затем с помощью свойства DataField подключите все DBEdit к соответствующему полю таблицы.
У компонента DBLookupComboBox установите следующие значения:
Таблица 5.3 . Значения свойств компонента DBLookupComboBox | |
Свойство |
Значение |
DataSource |
fDM.FoodDS |
DataField |
FType |
ListSource |
fDM.TipsDS |
KeyField |
TKey |
ListField |
TName |
Как видно из таблицы, компонент DBLookupComboBox имеет такие важные свойства:
Если говорить еще проще, то при открытии основного и подстановочного наборов данных, компонент DBLookupComboBox соединяется с подстановочной таблицей, указанной в свойстве ListSource, и формирует список значений из поля, указанного в ListField. Далее, при редактировании основной таблицы, пользователь выбирает из списка DBLookupComboBox одно из значений. При этом DBLookupComboBox смотрит, какое значение выбранной записи в подстановочной таблице имеет ключевое поле KeyField. Как правило, это целое число. Это число DBLookupComboBox и заносит в ссылочное поле основной таблицы DataField. Похожим образом действует и компонент DBLookupListBox, разумеется, учитывая специфику компонента.
Форма fEditor предназначена для редактирования имеющегося блюда или добавления нового, в зависимости от того, каким способом вызвали форму. Поэтому здесь нам нужно лишь создать код для события закрытия формы onClose, куда пропишем:
if fDM.FoodT.Modified then
if Application.MessageBox('Данные изменены! Сохранить?',
'Внимание!', MB_YESNO+MB_ICONQUESTION) <> IDYES then
fDM.FoodT.Cancel
else fDM.FoodT.Post;
Перейдем на главную форму. Командой
File -> Use Unit добавим к главной
форме новое окно. Пользователь должен
иметь возможность редактироват
fEditor.ShowModal;
Рядом с кнопкой "Типы блюд" добавим еще одну кнопку "Добавить блюдо". Сгенерируйте событие нажатия на эту кнопку и пропишите такой код:
fDM.FoodT.Append;
fEditor.ShowModal;
Как видите, отличие кода заключается лишь в том, что при нажатии на кнопку добавляется новая запись, открывается редактор и пользователь редактирует ее. А если он дважды щелкнет по записи на сетке, то откроется тот же редактор, в который будет загружена текущая запись. Впрочем, благодаря навигатору DBNavigator, пользователь и там имеет возможность перемещаться по записям, добавлять или удалять записи. Мы, собственно, получили далекую от идеала, но вполне работоспособную программу. Сохраните проект, скомпилируйте и введите для примера несколько блюд:
Рис. 5.8. Программа в действии
Как видите, программа имеет множество недостатков: пользователь видит совершенно ненужные ему ключевые поля, в сетке он видит лишь номер типа блюда, но не видит название этого типа. В поле FVeget ему вручную приходится писать True или False вместо привычных Да/Нет. Еще недостаток: названия полей в сетке соответствуют названиям полей в таблице, а поле "FType" или "FVeget" мало что скажет пользователю. Исправлением этих недостатков займемся в следующей лекции, вместе с изучением свойств полей.
6.
Лекция: Поля (TField): версия для печати и
PDA
На этой лекции вы познакомитесь с объектами-полями
и классом TField. Научитесь создавать и использовать
в наборах данных подстановочные и вычисляемые
поля , изучите наиболее важные свойства,
методы и события класса TField.
Каждая база данных состоит из таблиц, каждая таблица - из записей. Каждая запись в свою очередь представляет собой набор полей. Поле набора данных - это экземпляр достаточно мощного класса TField, о котором мы и поговорим на этой лекции.
Изучение свойств полей будем проводить на примере приложения из прошлой лекции.
Подстановочное поле Lookup изначально в набор данных не входит, его нужно создавать самостоятельно. Такое поле отличается от обычного тем, что показывает данные из другого набора данных. Для использования такого поля два набора данных обязательно должны иметь релятивную связь. На прошлой лекции мы применяли компонент DBLookupComboBox, который является аналогом подстановочного поля, но который нельзя показать в сетке DBGrid. При создании подстановочного поля также необходимо указать набор данных, откуда поле будет просматривать значения, ключевые поля для релятивной связи и поле со значениями, которые нужно подставлять.
Открываем проект из лекции № 5, открываем окно модуля данных. Дважды щелкаем по компоненту FoodT, чтобы открыть редактор полей. В этом редакторе у нас уже присутствуют пять полей, имеющихся в таблице, добавим шестое, подстановочное. Для этого щелкните правой кнопкой по редактору полей и выберите команду New Field (Новое поле):
Рис. 6.1. Создание подстановочного
(Lookup) поля
В разделе Field type (Тип поля) вы можете выбрать один из трех вариантов. Нас сейчас интересует тип Lookup. Заполните необходимые поля значениями, как на рисунке 6.1 и нажмите кнопку "ОК". Новое подстановочное поле будет добавлено в набор данных. В списке полей его можно переместить мышью на другое место, установите его сразу под FName. Перейдите на окно главной формы и убедитесь, что новое поле появилось. Однако оно пока еще не содержит данных - данные будут доступны только во время прогона программы. Сохраните проект, скомпилируйте и посмотрите, как работает программа. Как мы видим, теперь на главной форме два поля, которые ни к чему показывать пользователю - FKey с номерами записей, и FType - с номерами типов блюд, которые нам уже не нужны, поскольку мы показываем сами типы. Уберем их, точнее, сделаем невидимыми. Снова откройте редактор полей набора данных FoodT. Установите свойство Visible этих полей в False.
Как и подстановочное, вычисляемое поле изначально не входит в набор данных, а добавляется в процессе проектирования приложения. Вычисляемые поля предназначены для показа данных, которые автоматически вычисляются в процессе работы программы, используя одно или несколько полей набора данных. К примеру, в таблице имеется поле стоимости товара и количество, которое купил какой-то клиент. Вычисляемое поле, перемножив значения этих полей, может показать общую стоимость товара.
В нашем примере мы создадим вычисляемое поле для показа стоимости блюда в долларах США. Для этого в модуле данных создадим глобальную переменную dollar:
var
fDM: TfDM;
dollar: Currency = 30.36;
Вы можете указать текущий курс доллара к рублю, он так быстро меняется, что едва ли будет таким, как в моем примере. Итак, дважды щелкаем по набору данных FoodT, чтобы открыть редактор полей. Щелкаем правой кнопкой по этому редактору и выбираем команду "New field". В поле "Name" впишите название нового поля FDCena. В поле "Component" автоматически отобразится имя нового объекта-поля "FoodTFDCena", по которому в дальнейшем мы сможем к нему обращаться. Это имя составное - имя набора данных плюс имя нового поля, без всяких пробелов и разделителей.
В поле "Type" выберите тип Float, так как у нас могут быть копейки, вернее, центы. Затем убедитесь, что переключатель установлен на "Calculated" и нажмите "ОК". В редакторе полей появилось новое поле. Чтобы мы не получили сумму с кучей цифр после запятой, выделите в редакторе полей поле FDCena, и в его свойстве DisplayFormat укажите маску "#.## $US" (разумеется, без кавычек). К слову сказать, при создании вычисляемого поля мы могли бы выбрать тип Currency (денежный), но тогда к цифре добавлялось бы "р.", если ваша Windows имеет российские настройки.
Вещественные поля набора данных наряду с полями целого типа имеют четыре свойства, которые могут вам пригодиться:
DisplayFormat - Определяет формат отображения числа.
DisplayEdit - Определяет формат числа при редактировании.
MaxValue - Определяет максимально возможное для поля число.
MinValue - Определяет минимально возможное число.
Свойства MaxValue и MinValue по умолчанию имеют значение 0, что указывает на отсутствие ограничений.
Однако, это еще полдела. Поле мы сделали, осталось сделать вычисления. Код необходимых вычислений прописывается в свойстве OnCalcFields набора данных. Закройте редактор полей и выделите НД FoodT. Сгенерируйте для него обработчик события OnCalcFields и в этом обработчике пропишите следующую строчку:
FoodTFDCena.Value := FoodTFCena.Value / dollar;
Как видно из примера, мы используем значения одного или нескольких полей текущего набора данных, производим над ними какие то вычисления, и результат этих вычислений присваиваем вычисляемому полю.
Сохраните проект, скомпилируйте и посмотрите, как работает программа. Если вы все сделали правильно, у вас получится подобная картина:
Рис. 6.2. Подстановочное и вычисляемое
поле в программе
Если вы помните, при создании нового поля мы имеем три переключателя Field type. Переключатель "Data" предназначен для создания поля данных - пустого поля, которое программист использует по своему усмотрению. Наполнение этого столбца можно прописать в обработчике события OnGetText полученного объекта-поля. На практике такие поля используют редко, чаще они применяются для программного создания таблиц, о чем мы поговорим на одной из следующих лекций.
Свойство DisplayValues объекта-поля предназначено для отображения данных логического поля в нужном формате. Для примера изменим отображение данных поля FVeget. Откройте редактор полей компонента FoodT, выделите поле FVeget. В его свойстве DisplayValues укажите значение "Да;Нет". У логического поля вместо True и False здесь можно указать свою пару значений. Значение до точки с запятой считается истинным, значение после - ложным. Примеры:
Да;Нет
Муж;Жен
Yes;No
Y;N
Д;Н
и т.п. Указанные в свойстве значения пары "Истина;Ложь" будут отображаться в компонентах вывода данных, таких как DBGrid, DBEdit и т.п. Кроме того, эти же значения будут отображены, если вы будете получать значения этого поля с использованием свойства AsString, чтобы преобразовать значение в строковый тип.
Для облегчения пользователю ввода данных немного изменим проект. Откройте окно fEditor и удалите DBEdit, предназначенный для ввода логического значения в поле FVeget. Вместо него установите компонент DBComboBox. Дважды щелкните по свойству Items этого компонента и в открывшемся редакторе значений впишите две строки: