Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
61
Добавлен:
16.04.2013
Размер:
449.54 Кб
Скачать

2.2.5. Создание формы fmEditpers

Выберем команду File|New Form и нажмем в появившемся окне Browse Gallery кнопку OK, чтобы включить в проект пустую форму Blank form.

Поместим в эту форму 8 компонентов Label, 5 компонентов Button, 4 компонента DBEdit и по одному компоненту DBText, DBComboBox, DBLookupCombo, DBGrid, DBNavigator, расположив их так, как показано на рис.9. Поместим также на любое свободное место в форме 5 компонентов Table и 3 компонента DataSource.

Зададим для формы значение свойства Name=fmEDITPERS. Значения свойства Name для других компонентов установим в соответствии с указаниями, приведенными на рис.9, и рекомендациями, следующими за табл.3.

Значения свойства Caption для компонентов Label устанавливаются согласно надписям, поясняющим содержимое областей создаваемой формы и показанным на рис.9. Значение свойства Caption для компонентов Button задаются согласно надписям на кнопках (см. рис.9).

Свойства компонентов Table и DataSource устанавливаются в соответствии с табл.9-10.

Таблица 9

Значения свойств компонентов Table

Свойство

Компоненты

Table1

Table2

Table3

Table4

Table5

Name

taPERSON

taHAVE_D

taFLAT

taTPHONE

taPROFIT

DatabaseName

dbTUTOR

dbTUTOR

dbTUTOR

dbTUTOR

dbTUTOR

TableName

PERSON.DB

HAVE_D.DB

FLAT.DB

TPHONE.DB

PROFIT.DB

Active

True

True

True

True

True

Таблица 10

Значения свойств компонентов DataSource

Свойство

Компоненты

DataSource1

DataSource2

DatSource3

Name

dsPERSON

dsHAVE_D

dsFLAT

DataSet

taPERSON

taPERSON

taFLAT

С помощью Редактора полей для каждого компонента Table следует сформировать набор полей, используя последовательность действий, описанную в разделе 2.2.4 и поясненную на рис.11-12. Для таблиц taFLAT, taTPHONE и taPROFIT набор полей совпадает с перечнем полей (атрибутов) для находящейся в базе данных на диске таблицы с именем TableName, которая связана с компонентом Table.

Для таблицы taPERSON в набор полей включаются все поля, имеющиеся в таблице (файле) PERSON.DB, и одно вычисляемое поле Ntel типа StringField для хранения номера телефона, установленного в квартире. Для вычисления значения этого поля необходимо предусмотреть процедуру обработки события OnCalcFields для таблицы taPERSON. Текст этой процедуры, имя которой taPERSONCalcFields формируется автоматически системой Delphi, приведен на листинге 8. Значение вычисляемого поля Ntel таблицы taPERSON в процедуре обозначается как taPERSONNtel.Value.

Листинг 8. Процедура определения номера телефона

procedure TfmEDITPERS.taPERSONCalcFields(DataSet: TDataset);

begin

with taTPHONE do {Найти номер телефона по адресу}

begin

Open;

IndexName := 'Adr'; {Задать вторичный индекс}

First;

SetKey;

FieldByName('Adr').AsString :=

taPERSON.FieldByName('Adr').AsString;

if GotoKey then {Запись найдена по ключу}

taPERSONNtel.Value := FieldByName('Ntel').AsString

else {Запись не найдена}

taPERSONNtel.Value := '';

end;

end;

Для таблицы taHAVE_D в набор полей включаются все поля, имеющиеся в таблице (файле) HAVE_D.DB, и два вычисляемых поля: Source типа StringField с названием источника дохода и Size типа CurrencyField с размером дохода. Для вычисления значений этих полей необходимо предусмотреть процедуру обработки события OnCalcFields для таблицы taHAVE_D. Текст этой процедуры taHAVE_DCalcFields приведен на листинге 9. Значения вычисляемых полей отыскиваются в таблице taPROFIT по идентификатору вида дохода Id.

Листинг 9. Процедура вычисления полей Source и Size таблицы taHAVE_D

procedure TfmEDITPERS.taHAVE_DCalcFields(DataSet: TDataset);

begin

with taPROFIT do

begin

DisableControls;

Open;

First;

SetKey;

FieldByName('Id').AsInteger :=

fmEDITPERS.taHAVE_D.FieldByName('Id').AsInteger;

GotoKey; {Поиск записи по ключу}

EnableControls;

end;

taHAVE_DSource.Value := taPROFITSource.Value;

taHAVE_DSize.Value := taPROFITMoneys.Value;

end;

Данные из таблицы taHAVE_D будут отображаться в компоненте grHAVE_D. Чтобы на экране были видны значения только полей Source, Size и Comment с соответствующими заголовками “Источник”, “Размер”, “Пояснение”, значения свойств полей в сформированном наборе должны быть установлены согласно табл.11.

Таблица 11

Значения свойств полей для компонента taHAVE_D

FieldName

Calculated

DisplayLabel

Visible

Nom

False

Nom

False

Id

False

Id

False

Source

True

Источник

True

Size

True

Размер

True

Comment

True

Пояснение

True

Значения свойств, общих для визуальных компонентов, управляющих данными, задаются в соответствии с табл.12. Для компонента dcPol дополнительно устанавливается значение свойства Items, содержащего допустимое обозначение пола, которое помещается в поле Pol таблицы taPERSON. Действия по установке значения свойства Items описаны в разделе 2.2.3. Для компонента deSumD дополнительно задается значение свойства ReadOnly=True, чтобы запретить запись общего дохода с помощью клавиатуры, поскольку целесообразно общий доход вычислять автоматически на основе данных, имеющихся в таблицах taHAVE_D и taPROFIT.

Таблица 12

Значения общих cвойств визуальных компонентов

Name

DataSource

DataField

Name

DataSource

DataField

teNom

dsPERSON

Nom

deSumD

dsPERSON

SumD

deFIO

dsPERSON

FIO

deNtel

dsPERSON

Ntel

deRdate

dsPERSON

Rdate

grHAVE_D

dsHAVE_D

--

dcPol

dsPERSON

Pol

naHAVE_D

dsHAVE_D

--

lcAdr

dsPERSON

Adr

Для компонента naHAVE_D дополнительно устанавливается значение свойства VisibleButtons=[nbFirst,nbPrior, nbNext, nbLast, nbDelete, nbEdit, nbPost, nbCancel], поскольку вместо кнопки навигатора nbInsert в форме предусмотрена кнопка “Новый доход”.

С помощью компонента lcAdr значение поля Adr таблицы taPERSON устанавливается путем выбора из списка возможных значений, хранящихся в таблице taFLAT; список появляется при щелчке на кнопке со стрелкой. Для настройки компонента lcAdr нужно задать значения свойств DataSource и DataField, указанное в табл.12, а также значения свойств LookupSource, LookupField, LookupDisplay, необходимые для связи с таблицей taFLAT: LookupSource=dsFLAT (DataSource, соответствующий таблице taFLAT); LookupField=Adr (ключевое поле таблицы taFLAT, значение которого должно соответствовать значению поля, указанного в свойстве DataField); LookupDisplay=Adr (поле таблицы taFLAT, значение которого отображается на экране в компоненте lcAdr).

Примечание.Компонент DBLookupCombo обеспечивает равенство значений полей DataField и LookupField в таблицах, связанных с DataSource и LookupSource соответственно, и позволяет отображать значение поля LookupDisplay на экране в компоненте DBLookupCombo.

В компоненте grHAVE_Dдолжны отображаться виды доходов жителя, номер которого выводится в области компонентаteNom. Для этого между таблицамиtaPERSON иtaHAVE_Dнеобходимо установить связь “главная/подчиненная”(master/detailed), задав следующие значения свойств подчиненной таблицыtaHAVE_D:MasterSource=dsPERSON; MasterFields=Nom. Строки (записи) в подчиненной таблице должны быть упорядочены с помощью существующего индекса по значениям полей, соответствующих полям, указанным в свойствеMasterFields.Для таблицыtaHAVE_Dдействует первичный индекс с составным ключом(Nom, Id), обеспечивающим автоматическую сортировку по значениям поляNom, поэтому специального указания об используемом индексе не требуется, хотя можно было бы установить свойствоIndexFieldNames=Nom для полной ясности.

Для вычисления общего дохода жителя и записи его в поле SumD таблицыtaPERSONпоместим в форму компонентQuery со страницыData Accessпалитры компонентов и зададим его свойстваName=quSumD, DatabaseName=dbTUTOR.Затем дважды щелкнем на свойствеSQL и в появившемся окнеString list editor наберем запрос на языкеSQL, с помощью которого будет вычисляться общий доход жителя, помещаемый в полеSummaкомпонентаquSumD (см. листинг 10).

Листинг 10.SQL-запрос для вычисления общего дохода

selectSUM(PROFIT.Moneys) Summa, HAVE_D.Nom

fromHAVE_D, PROFIT

whereHAVE_D.Id=PROFIT.IdandHAVE_D.Nom=:Nom

group byNom

Параметром SQL-запроса является величина:Nom, обозначающая номер жителя. Тип параметра(Integer) задается как значение свойстваParams компонентаquSumD. С помощью Редактора полей для компонентаquSumD следует сформировать набор полей, включив в него полеSumma.

SQL-запрос должен выполняться каждый раз после записи новой строки в таблицуtaHAVE_Dили после удаления строки из нее, т.е. при наступлении событияAfterPost илиAfterDelete.Текст процедуры обработки событияAfterPost приведен на листинге 11.

Листинг 11. Процедура вычисления общего дохода

procedure TfmEDITPERS.taHAVE_DAfterPost(DataSet: TDataset);

begin

with quSumD do

begin

if Active then Close; {Закрыть таблицу}

ParamByName('Nom').AsInteger:=taPERSONNom.AsInteger; {Задать значение параметра}

Open; {Выполнить SQL-запрос}

taPERSONSumD.Value:=quSumDSumma.Value; {Записать общий доход}

end;

end;

Эта же процедура должна выполняться при наступлении события AfterDelete.Чтобы использовать ее повторно, нужно для таблицыtaHAVE_Dв окне Инспектора объектов на странице событий выделить строку, соответствующую событиюAfterDelete, щелкнуть в этой строке на кнопке со стрелкой и выбрать из появившегося списка имя процедурыtaHAVE_DAfterPost.

Теперь перейдем к компонентам Button.Для кнопок “Отмена” и “Выход” процедуры обработки событияOnClick во многом сходны с ранее рассмотренными (см. листинг 3) и приведены на листинге 12.

Листинг 12. Процедуры обработки события OnClick для

кнопок Отмена и Выход

procedure TfmEDITPERS.buCancelClick(Sender: TObject);

begin

with taPERSON do

begin

Cancel; { Отменить изменения, }

Edit; { но }

taHAVE_DAfterPost(taHAVE_D); { вычислить и }

Post; { запомнить общий доход }

end;

fmEDITPERS.Close;

end;

procedure TfmEDITPERS.buExitClick(Sender: TObject);

begin

with taPERSON do

begin

if (State in [dsEdit,dsInsert]) and Modified then

Post; {Сохранить изменения, если действует режим }

end; {редактирования или дополнения и запись изменялась}

KeyValue := {Запомнить значение ключа для fmSHOWPERS }

taPERSON.FieldByName('Nom').AsInteger;

fmEDITPERS.Close;

end;

Процедура обработки события OnClickдля кнопки “Сведения о квартире” активизирует формуfmEDITFLAT для просмотра, изменения или регистрации сведений о квартире (см. листинг 13). Если регистрируется новая квартира, то сведения о ней должны быть отражены в таблицеtaFLAT,принадлежащей формеfmEDITPERS, иначе новый адрес не будет появляться в списке связанном с компонентомlcAdr.Для обновления таблицыtaFLAT после возврата из формыfmEDITFLATвызывается процедураRefresh_taFLAT,текст которой приведен на листинге 13. Заголовок процедурыRefresh_taFLAT помещается в разделеprivate классаTfmEDITPERS.

Листинг 13. Процедуры обработки события OnClick для кнопки

Сведения о квартире и обновления таблицы taFLAT

procedure TfmEDITPERS.buEditFlatClick(Sender: TObject);

begin

if taPERSONAdr.Value='' then {Адрес отсутствует }

begin

fmEDITFLAT.Editing :=False;

fmEDITFLAT.KeyValue:='';

end

else

begin

fmEDITFLAT.Editing := True;

fmEDITFLAT.KeyValue:= taPERSONAdr.Value;

end;

fmEDITFLAT.ShowModal;

Refresh_taFLAT; {Обновить таблицу }

if (fmEDITFLAT.KeyValue<>'')then

begin {Адрес задан }

lcAdr.DisplayValue := fmEDITFLAT.KeyValue; {Показать адрес }

taPERSONAdr.Value := fmEDITFLAT.KeyValue; {Записать адрес }

taPERSONCalcFields(taPERSON); {Вычислить номер телефона}

end;

end;

procedure TfmEDITPERS.Refresh_taFLAT;

begin

with taFLAT do

begin

First;

SetKey;

FieldByName('Adr').AsString := fmEDITFLAT.KeyValue;

GotoKey; {Поиск записи по ключу }

end;

end;

Процедура обработки события OnClick для кнопки “Сведения о телефоне” активизирует форму fmEDITPHON для просмотра, изменения или регистрации сведений о телефоне (см. листинг 14). Если регистрируется новый телефон, то сведения о нем будут отражены в таблице taTPHONE, принадлежащей форме fmEDITPERS, при поиске номера телефона по адресу процедурой taRERSONCalcFields.

Листинг 14. Процедура обработки события OnClick для

кнопки Сведения о телефоне

procedure TfmEDITPERS.buEditPhoneClick(Sender: TObject);

begin

if taPERSONNtel.Value='' then {Телефон отсутствует }

begin

fmEDITPHON.Editing := False;

fmEDITPHON.KeyValue:= ''; {Если не изменится,то была Отмена}

end

else

begin

fmEDITPHON.Editing := True;

fmEDITPHON.KeyValue:= taPERSONNtel.Value;

end;

fmEDITPHON.ShowModal;

taPERSONCalcFields(taPERSON); {Вычислить номер телефона }

end;

Процедура обработки события OnClick для кнопки “Новый доход” добавляет новую строку в таблицуtaHAVE_D и активизирует формуfmEDITPROF,используемую для выбора нужного вида дохода (см. листинг 15). После возврата из формыfmEDITPROFзаполняются поляNom иIdдобавленной строки в таблицеtaHAVE_Dи строка записывается в таблицу.

Листинг 15. Процедура обработки события OnClick

для кнопки Новый доход

procedure TfmEDITPERS.buNewProfitClick(Sender: TObject);

begin

taHAVE_D.Append;

fmEDITPROF.Editing := True;

fmEDITPROF.KeyValue:= 0;

fmEDITPROF.ShowModal;

if fmEDITPROF.KeyValue>0 then {Выбор сделан}

begin

with taPERSON do

if (State in [dsEdit,dsInsert]) and Modified then

begin

Post; {Сохранить изменения, если действует режим редак-}

{тирования или дополнения и запись изменялась, }

Edit; { чтобы установить значение поля Nom}

end;

taHAVE_DNom.Value := taPERSONNom.Value;

taHAVE_DId.Value := fmEDITPROF.KeyValue;

taHAVE_D.Post;

end

else {Выбор не сделан}

taHAVE_D.Cancel;

end;

В процедуре учтена особенность полей типа Autoincrement: при добавлении новой строки в таблицу методомAppend илиInsertзначение в поле этого типа заносится только после выполнения методаPost для таблицы.

Для автоматического определения номера телефона по заданному адресу предусмотрим для компонента lcAdrпроцедуру обработки событияOnChange,которое наступает при переходе фокуса из области компонентаlcAdr, если изменилось значение адреса. Текст процедуры показан на листинге 16.

Листинг 16. Процедура обработки события OnChange

для компонента lcAdr

procedure TfmEDITPERS.lcAdrChange(Sender: TObject);

begin

with taPERSON do

if (State in [dsEdit,dsInsert]) and Modified then

taPERSONCalcFields(taPERSON); {Определить номер телефона}

end;

Создаваемая форма может вызываться в режимах регистрации или изменения сведений о жителе. При активизации формы fmEDITPERSнеобходимо задать соответствующий заголовок формы и обеспечить доступ к нужной записи таблицы taPERSON.Эти действия выполнит процедура обработки событияOnActivate,текст которой приведен на листинге 17.

Листинг 17. Процедура обработки события OnActivate

procedure TfmEDITPERS.FormActivate(Sender: TObject);

begin

if Editing then

begin

Caption := 'Изменение сведений о жителе';

with taPERSON do

begin

DisableControls;

First;

SetKey;

FieldByName('Nom').AsInteger := KeyValue;

GotoKey; {Поиск записи по ключу}

EnableControls;

Edit; {Режим редактирования}

end;

end

else

begin

Caption := 'Регистрация сведений о жителе';

taPERSON.Append; {Режим дополнения }

end;

end;

В этой и других процедурах используется признак режима EditingтипаBooleanи признакKeyValueтипаLongint,содержащий значение первичного ключа таблицыtaPERSON.Эти переменные следует объявить в разделеpublicклассаTfmEDITPERS.

Создаваемая форма активизирует формы fmEDITFLAT, fmEDITPROF иfmEDITPHON.Чтобы они были доступны, в разделImplementationмодуля создаваемой формы следует поместить предложение

uses EDITFLAT, EDITPROF, EDITPHON;

Сохраним созданную форму и проект командой File|Save Project, указав в качестве имени модуля созданной формы имяEDITPERS.На этом создание формыfmEDITPERSзавершается. Остается связать ее с пунктом меню “Житель” в главной форме и с кнопкой на панели быстрого доступаsbNewPerson аналогично тому, как подобные связи устанавливались для формыfmEDITFLAT (см. окончание раздела 2.2.3).

Сохранив изменения командой File|Save Project, можно проверить работоспособность проекта, осуществив активизацию созданной формы из меню или кнопкой на панели быстрого доступа и убедившись в правильном функционировании формыfmEDITPERS.

  1. Лабораторное задание

Ознакомиться с методикой построения прикладной системы для работы с базой данных, освоить методику на примере учебного задания и использовать ее для выполнения конкретного варианта задания.

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Мы не исправляем ошибки в тексте (почему?), но будем благодарны, если вы все же напишите об ошибках.