Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2852
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

/2. Разработка библиотеки интерфейсных компонентов

Записная книжка

Создать/

Записать

Найти

 

открыть

 

телефон

телефон

 

книжку

 

 

 

 

Рис. 12.1. Окно главного меню

Главное

меню

Создание/

Добавление

Поиск

открытие

записей

записей

файла

 

 

Рис. 12.2. Диаграмма переходов состояний интерфейса:

1 - 4 - выбор пунктов «Открытие файла», «Добавление записей», «По­ иск записей» и «Выход» соответственно; 5 - выбор пунктов «Выход» на формах «Открытие файла», «Добавление записей», «Поиск записей»

Каждая функция будет выполняться в своем окне. По необходимости ок­ на функций будут иметь локальные меню, управление которыми также будет осуществляться с помощью клавиатуры.

При выполнении пункта «Создать или открыть книжку» на экране долж­ но появиться окно ввода имени файла (рис. 12.3), причем до ввода имени файла выбор прочих пунктов меню, кроме «Завершения работы», должен

быть блокирован. После ввода имени файла, кото­

 

 

рое должно быть проверено с точки зрения синтак­

iliiiilll^

 

сиса имен файлов, программа будет пытаться от­

 

крыть файл. Если файл с указанным именем не бу­

 

 

дет обнаружен, то она создаст файл с таким име­

1©| ^

|jij

нем.

[;-;:;f••\*if i^rl

 

При выборе пункта «Добавление записей» на

 

рис. 12.3, Окно

 

экране должна появляться форма ввода записей

 

(рис. 12.4), которая содержит поля ввода и локаль-

ввода имени файла

 

361

Часть 2. Объектно-ориентированное программирование

 

 

ное меню. Добавление записей происходит

и^:ШИсе||::,,'З;;-^^^

при выборе пункта «Добавить» локального

У •

1 1

меню. При этом все поля очищаются, а

;П|':-:-,1:^^

 

курсор вновь устанавливается в поле ввода

щ

Шщ

фамилии.

 

 

Добавляемая информация может быть

 

 

не полной, например, может быть известно

1 Добавить 1

 

только имя или только фамилия абонента,

 

тогда пользователь должен перейти в сле­

Рис. 12.4. Форма ввода

дующее поле формы, нажав клавишу Enter:

соответствующее поле записи файла будет

записей

пустым. После внесения всех записей

 

пользователь должен выбрать пункт «Выход» и вновь вернуться в главное меню.

При выборе пункта «Поиск записей» на экране должна появляться фор­ ма поиска (рис. 12.5, а\ которая содержит поле ввода фамилии, имени, поле вывода телефона и локальное меню из трех пунктов. Поиск должен осуще­ ствляться по вводу фамилии и/или имени. Начало поиска по выбору пункта «Поиск». Если запись не найдена, то программа должна выдавать сообщение об отсутствии данных (рис. 12.5, б). Если необходимо найти несколько запи­ сей, то переход к поиску следующей записи осуществляется по выбору пунк­ та «Следующий» (рис. 12.6). После завершения поиска пользователь вновь должен вернуться в главное меню, выбрав пункт «Выход».

Осуществим объекгную декомпозицию программы. Будем считать, что каждому элементу интерфейса соответствует интерфейсный объект. Полу­ ченная при этом диаграмма интерфейсных объектов - результат объектной

;;:;:J;;^';;:;;;rt::t;r

[•':::: ;:';;,::ШшШШ^'';^^^

||'•;;^^a<^n^

f-:••'';•:'^;^f^l|||iJ:^^

1ш1Ш111111111111Ш

11 Найти II Следующий

i': •?. "'

.::" • • '••-••

''••••yy.y:^!\i'jfi^^^^

Рис. 12.5. Форма поиска записей {а) и сообщение об отсутствии данных (б)

362

12. Разработка библиотеки интерфейсных компонентов

^

Ввод

1[Запись \найдена!

2 [Запись шшдена]

W

данных

Г

i

 

^

 

J

Л

 

1

\

 

Вывод

V

[Заг1ись не

\

данных

 

 

найдена]

 

 

2 [Запись не найдена]

 

 

 

 

\

 

 

'Запись не

 

 

 

 

 

 

-п^5'

 

 

найдена"

4

 

 

 

 

 

Рис. 12.6. Диаграмма перехода состояний для интер­ фейса пункта «Поиск записей»:

1 -

выбор пункта «Поидк»; 2 - выбор пункта «Следующий»;

3

- выбор пункта «Выход»; 4 - подтверждение получения

 

сообщения об отсутствии данных

декомпозиции интерфейсной части предметной области программы - приве­ дена на рис. 12.7.

Описание объектов начнем с того, что расположим окна в порядке воз­ растания сложности. При этом просматривается определенная закономер­ ность.

Анализ окон показывает, что их четыре вида:

а) окно ввода информации (рис. 12.8, а) - пассивное окно, которое долж­ но закрываться при завершении ввода данных (по нажатию Enter);

Главное

меню

 

Активизировать

^

v,^^^

Активизировать

 

Г

 

Л

 

' Активизировать ^'"'^^v,^^

 

Ввод

 

Добавление

•"

Поиск

^

 

 

 

 

 

 

имени файла

 

 

записей

 

записей

 

 

 

 

 

Активизировать

 

 

 

 

 

 

 

'

]

 

 

 

 

 

 

Сообщение об

 

 

 

 

 

 

отсутствии

 

 

 

 

 

 

^

данных

J

Рис. 12.7. Диаграмма объектов - результат декомпозиции интерфейсной части предметной области программы

363

Часть 2. Объектно-ориентированное программирование

Введите имя-файла:

1 1 home.dat | |

 

Записная книжка

Создать/

Записать

Найти

открыть

телефон

телефон

книжку

 

 

Добавлен1ие записей

 

 

Поиск записей

Фамилия

1

Иванов

1

1

Фамилия

Иванов

Имя

1

Иван

1

1

Имя

Иван

Телефон

1

11 П И !

1

 

Телефон

1111111

1 Добавить]

 

 

 

I [

Найти Bii^^eM

Выход 1 1

Рис. 12.8. Определение структуры окон программы

б) окно сообщения (рис. 12.8, б) - активное окно, которое ожидает нажа­ тия любой клавиши - подтверждения получения сообщения;

в) меню (рис. 12.8, в) - активное окно, которое циклически обрабатыва­ ет выбор некоторого пункта пользователем и закрывается при выборе пунк­ та «Выход»;

г) форма, включающая окна ввода и меню (рис. 12.8, г, д) - активное ок­ но, которое помимо циклической обработки выбора пункта обеспечивает возможность осуществления ввода-вывода информации.

Отсюда следует, что достаточно иметь четыре настраиваемых компонен­ та - по одному для реализации объектов каждого вида (рис. 12.9).

364

12, Разработка библиотеки интерфейсных компонентов

Щ|3<?Щ|^^^

 

 

 

t ^ ' : , ' ::»:-^'>. ::*,:::•••

 

••-•::^. ^^v-Cw. :v|;::::i:v::••:;.;„•;:•:

:•-:•:'••С^/^:^Гг:г<Л:?^^т:-.г..

<текст>

ШШ-МгЩ

|:f::;;';.-i;'?!*^

''?ШШЩ&ЩЩ^*^^:»ьЩШ:''У¥ШШ$щ

|Ш||:Щ

 

<текст>

Ьр-:,Ш:Щ

 

 

^А'--> .:•.,-:,-...;•::!•:••

 

 

 

 

 

Ж^|

 

<текст>

1^; ••••"•'::•: Ч

]

< :я»!.*«»«*,л!^^»*^» * * » | * *»!*S»y* *: • *** *•* ' ,,,.^*.,««, ,,,,,.»,«,,,.•.,*..,»,* -.

\

<текст>

<текст> 1

^^^^^^ИШ й

 

• ;/ \^__ \ ,11,,,.,,и,,,,,,ми,,,

Рис. 12.9. Обобщенное представление компонентов интерфейса (пунктиром выделены компоненты ввода на форме)

Уточнив характеристики интерфейсных компонентов, переходим к их проектированию.

12.2. Проектирование классов

Нетрудно видеть, что любое окно на рис. 12.9 включает строку текста. Следовательно, классы для соответствующих объектов можно наследовать от класса, реализующего окно со строкой текста.

Анализ обобщенных представлений также показывает, что каждая фор­ ма включает несколько окон с текстом в качестве пунктов меню, окон ввода и т.д.; соответственно помимо наследования при построении классов будем использовать композицию.

365

Часть 2. Объектно-ориентированное

программирование

 

TWin

 

 

х1, у1, х2, у2, attr, xt, yt, text

 

Draw(), SetAttr(), Init()

 

TInput

TMessage

TMenu

inp:TWin

ok:TWin

nalt, npos,

Draw(), Init(), Input(),

Draw(), Init(),

masalt:array[1..10] of TWin

Enov{ \ Clear()

RunQ

Run(), Draw(),IEnterQ, InitQ

 

 

TForm

 

ninput, masinp:an-ay[1..5] ofTInput

 

Draw(), EnterO, Input(), CIear(), Init()

Рис. 12.10. Иерархия классов для реализации простейших интерфейсных элементов

Для реализации каждого вида окон будем строить свой класс. Вспомогательный базовый класс TWin, реализующий окно с текстом,

должен содержать поля для хранения координат окна, цвета фона, цвета сим­ волов, координат начала текста и самой строки текста. Цвет фона и цвет сим­ вола будем хранить в одном поле attr в виде атрибута - см. параграф 8.1. Для вывода окна класс должен включать метод Draw, для изменения цвета окна - метод SetAttr. Инициализацию полей будет выполнять метод Init (рис. 12.10).

Класс для реализации окна ввода TInput наследуем от TWin и включим в него объектное поле inp типа TWin, которое будет содержать введенное имя файла в качестве текста (на рис. 12.10 композиция не показана, чтобы не за­ тенять общую картину). Класс будет определять свои собственные методы инициализации Init и рисования Draw, так как он должен рисовать два окна с текстом и соответственно хранить информацию о них. Кроме этого класс должен включать метод ввода Input, метод проверки правильности ввода Error, метод очистки поля ввода Clear, которые будут обеспечивать ввод ин­ формации.

Класс для реализации сообщения TMessage также наследуем от TWin. Объектное поле ок введено для подтверждения получения сообщения. Класс будет включать методы вывода окна Draw, инициализации полей Init и метод Run, обеспечивающий выход по нажатию любой клавиши.

Класс для реализации меню TMenu будем наследовать от TWin, так как если его наследовать от TMessage, то объекты будут содержать лишнее поле ок. Этот класс будет включать несколько, например десять, объектных полей типа TWin, собранных в массив masalt. Каждое из полей ~ пункт меню. Ко­ личество реально существующих пунктов будем хранить в специальном по­ ле nalt. В процессе работы с меню необходимо также знать номер выделен-

366

12. Разработка библиотеки интерфейсных компонентов

ного пункта меню проз. Метод Run будет обеспечивать работу с меню. Для вывода меню на экран он будет вызывать метод Draw, также переопределен­ ный в данном классе. Каждый раз при выборе пункта меню метод Run будет вызывать метод Enter, который обеспечит выполнение требуемых действий. Для инициализации полей класса TMenu переопределим метод Init.

Класс для реализации форм ввода и поиска TForm наследуем от TMenu, чтобы повторно не описывать работу с меню. Для ввода-вывода информации добавим окна ввода, объединенные в массив masinp, количество используе­ мых окон ввода будем хранить в поле ninput. Метод Run данный класс будет наследовать, а вызываемые из него методы Draw и Enter - переопределять. Следовательно, и в классе TMenu, и в классе TForm методы Draw и Enter должны объявляться виртуальными полиморфными (1-й случай обязатель­ ного использования позднего связывания). Кроме реализации меню класс TForm должен обеспечивать выполнение операций ввода-вывода. Следова­ тельно, он будет включать методы ввода Input и очистки полей Clear.

При проектировании классов те методы, реализация которых будет зави­ сеть от конкретной задачи, программируются не содержащими действий (аб­ страктными). Предполагается, что они будут переопределяться при наследо­ вании класса от библиотечного.

12.3. Реализация универсальных интерфейсных компонентов

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

К л а с с T W i n описываем в модуле Win: в интерфейсной части - са­ мо описание класса, а в части реализации - методы класса.

Unit Win;

 

Interface

 

Uses crt;

 

Type str80=stnngf80J;

 

TWin-=Object

 

xly yly x2, у2:integer;

{координаты окна}

attr:integer;

{атрибут}

xt, yt:integer;

{начало текста}

text:str80;

{строка текста}

procedure Init(ax1, ayI, ax2, ау2, aattr, axt, ayt: integer;atext:str80);

procedure SetAttr(aattr:integer); {изменение цвета и фона окна}

procedure Draw;

{вывод окна на экран}

End;

 

367

Часть 2, Объектно-ориентированное программирование

Implementation

Procedure TWinJnit; {инициализация полей}

Begin

х1:'=^ах1; у1:-^ау1; х2:='ах2; у2:^ау2; attr:-aattr; xt:=axt; yt:=ayt; text:==atext;

End;

Procedure TWin.Draw; {вывод окна на экран} Begin

TextBackGround(attr div 16); TextColorfattr mod 16); Window(xl,yl,x2,y2);

Clrscr; {выделение окна}

Gotoxy(xt,yt);

Write(text); {вывод строки текста}

end;

Procedure TWin.Setattr; {изменение цвета фона и текста}

Begin

 

attr: =aattr;

{изменение атрибута}

Draw;

{вывод окна с другим атрибутом}

end;

 

End

 

К л а с с T I n p u t

описываем в модуле Input. Метод Error объявляем

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

Unit Input;

Interface

Uses crt, Win;

Type TInput=-Object(TWin)

inp:TWin;

{окно ввода}

Constructor Init(axl,ayl,ax2,ay2,aattr,axt,ayt:integer;atext:str80; bxlybylybx2yby2ybattrybxtybyt:integer;btext:str80);

procedure Draw; {вывод окна} procedure Clear; {очистка поля ввода}

368

12. Разработка библиотеки интерфейсных компонентов

procedure Input; (ввод строки из окна} function Error:boolean; virtual; {проверка введенных данных}

end; Implementation

Constructor TInputJnit; Begin

inherited Init(axl, ayI, ax2, ay2, aattr, axt, ayt, atext); Inp.Init(bxI, byJ, bx2, by2, battr, bxt, byU ');

end;

Procedure TInput.Draw; Begin

inherited Draw; inp.Draw;

End;

Procedure TInput. Clear; Begin

inp.text:-**; inp.Draw;

End;

Procedure TInput.Input; Begin

Window(inp.xl, inp.yl, inp.x2, inp.y2); TextBackGround(inpMttr div 16); TextColorfinp.attr mod 16);

repeat

Gotoxy(inp.xt, inp.yt); Clear;

ReadLnfinp, text); Gotoxyfinp.xt, inp.yt); Write(inp.text);

until not Error;

end;

Function TInput.Error; {проверка не выполняется} begin

Error: "^false; end;

End

К л а с с T M e s s a g e описываем в модуле Message.

Unit Message;

Interface

Uses crty Win;

369

Часть 2. Объектно-ориентированное программирование

Туре TMessage='Object(TWin)

ok:TWm; {окно подтверждения}

procedure Init(axl, ayj, ах2, ау2, aattr, cat, ayt: integer;atext:str80; bxl, by], bx2, by2, battn bxt, byt:integer;btext:str80);

procedure Run; {ожидание подтверждения} procedure Draw; {вывести окно}

end; Implementation

Procedure TMessage.Init; Begin

inherited Initfaxl, ayl, ax2, ay2, aattr, cat, ayt, atext); ok.Initfbxl, by], bx2, by2, battr, bxt, byt, btext);

end;

Procedure TMessage.Draw; Begin

inherited Draw; {выводим родительское окно}

okDraw; {выводим окно запроса на продолжение работы}

End;

Procedure TMessage.Run; Begin

Draw; {выводим окно}

ReadKey; {ожидаем подтверждения}.

End;

End.

К л а с с T M e n u описываем в модуле Menu. Инициализацию объект­ ных полей-массивов целесообразно выполнять типизированными константа­ ми. Несовпадения размерности массивов, если используются не все пункты меню, можно избежать, описав параметры как открытые массивы, не забыв, что индекс элементов открытого массива начинается с нуля.

Unit Menu;

 

Interface

 

Uses crt, Win;

 

Type TMenu'=^Object(TWin)

 

nalt:integer;

{количество альтернатив в меню}

masalt:array[L.10] ofTWin; {массив альтернатив меню}

npos'.integer;

{номер выбранной альтернативы}

constructor Initfaxl,ayl ,ах2,ау2,aattr,

axt, ayt:integer;atext:str80;n:integer;

const w:array ofTWin); {открытый массив TWin}

procedure Run;

{реализация работы с меню}

procedure Draw; virtual;

{вывести окно}

370