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

Delphi

.pdf
Скачиваний:
27
Добавлен:
13.04.2015
Размер:
1.18 Mб
Скачать

3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal

F = (x2

− 5)3

a = 5, b = 10

;

10. 1

 

 

 

,

1

1

F2

=

1

 

 

a2 = 2, b2 = 5 ;

 

 

 

 

 

x ln x ,

 

 

F = tg

π

 

a3 = −1, b3 = 1.

 

3

 

 

x

2 ,

 

 

 

Контрольные вопросы для сдачи лабораторной работы:

1.Расскажите идею метода трапеций.

2.Как в процедуру передать имя функции?

3.Можно ли имени процедуры присваивать какие-либо значения?

4.Могут ли разные процедуры иметь одно и то же имя?

5.Перечислите все способы передачи параметров в процедурах.

3.8 КЛАССЫ, ОБЪЕКТЫ

Ранее уже рассматривались понятия классов и объектов на относительно интуитивном уровне. В этом разделе мы рассмотрим как самостоятельно описать новый класс данных, наделить его свойствами и методами. Напомним, что классы и их экземпляры, т.е. объекты можно представлять как записи, которые помимо данных (поля записи) содержат процедуры и функции (методы класса), а также свойства.

3.8.1 Описание классов

Класс новых объектов может описываться в виде:

Type

TChildObject = class(TParentObject)

{Описание данных класса:}

Var1 : Integer;

Var2 : Double;

...

{Описание методов класса:}

Procedure SetVar1(aVar1: Integer); Function F5: String;

...

{Описание свойств класса:}

Property PropVar1: Integer read Var1 write SetVar1;

...

90

3.8 КЛАССЫ, ОБЪЕКТЫ

end;

Методы описанного класса TChildObject, созданного на основе родительского класса TParentObject, определяются подобно обычным процедурам и функциям. Единственное отличие – это добавление имени объекта перед именем метода:

Procedure TChildObject.SetVar1(aVar1: Integer); begin

{код процедуры, например:}

If SetVar1<>aVar1 Then SetVar1:=aVar1; end;

Переменные, описанные с помощью свойства Property, отображаются в окне инспектора объектов Delphi. Назначение процедуры SetVar1 состоит в присваивании полю Var1 некоторого значения. Когда запрашивается (read) свойство PropVar1, оно считывается из поля Var1 и возвращается. При присвоении (write) свойству PropVar1 некоторого значения вызывается процедура SetVar1, предназначенная для изменения значения поля Var1.

Object Pascal может ограничивать степень доступа к полям и методам объекта с помощью директив:

Private – объявления данного класса доступны только в текущем модуле. Директива скрывает особенности реализации класса и не позволяет их изменять из вне;

Protected – члены объекта доступны, объектам, произведенным от этого класса. Директива скрывает особенности реализации класса, но позволяет его потомкам работать с ним;

Public – члены объекта доступны в любом месте программы; Published – позволяет другим элементам приложения получать информацию об элементах данного объекта только через его свойства и методы. Прямой доступ к его данным запрещен.

Ниже показано объявление свойства PropVar1 в классе TChildObject, которое повышает его целостность и логичность:

Type

TChildObject = class(TParentObject)

Var1 : Integer;

...

Procedure SetVar1(aVar1: Integer);

...

Published

91

3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal

Property PropVar1: Integer read Var1 write SetVar1;

...

end;

Теперь ни один из пользователей этого класса не сможет изменить значение Var1 непосредственно, и вынужден будет использовать свойство PropVar1. С другими примерами директив Вы уже встречались в разделах «Структура модуля» и «Начинаем программировать»

3.8.2 Создание и удаление объектов

После объявления класса (типа) объектов, можно выполнить объявление переменных (экземпляров) данного класса. Для предыдущих примеров такое объявление может иметь вид:

Var Object1 : TChildObject;

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

Object1:= TChildObject.Create;

После окончания использования объекта следует освободить выделенную для него память методом деструктора объектов:

Object1.Free;

Может возникнуть вопрос: откуда берутся все эти конструкторы и деструкторы? Неужели их необходимо всегда описывать? Конечно, нет. Дело в том, что все классы Object Pascal наследуют методы базового класса TObject (см. приложение 2), где они и описаны.

3.9 ОБРАБОТКА ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ

Исключительные ситуации, или просто, «исключения» – это ошибки, возникающие во время выполнения приложении, например, деление на ноль, попытка чтения данных из несуществующего файла и т.д. Когда возникает исключение – появляется диалоговое окно, описывающее тип ошибки с кнопкой OK. Если программист не предусмотрел специальных средств обработки возникшего исключения, то после щелчка на кнопке OK вызывается стандартная процедура обработки исключения.

92

3.9 ОБРАБОТКА ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ

Object Pascal имеет мощный механизм создания и обработки исключений. Использование вполне «мирных» искусственных исключений позволяет элегантно строить взаимодействие между пользователем и многочисленными блоками программы.

3.9.1 Исключения (Exception, Raise)

Существует много типов стандартных исключений. Некоторые из них приведены в приложении 6. Для анализа нестандартных ситуаций, возникающих в разных глубоко вложенных блоках программы, удобно использовать искусственные исключения. Они позволяют сразу же выйти в главный блок, централизованно проанализировать возникшую ситуацию, организовать необходимый диалог с пользователем и обработать исключение соответствующим методом. Такой механизм позволяет избежать многоступенчатого использования преторов выхода Exit с многочисленной передачей параметров-условий выхода.

Все исключения принадлежат классу Exception. Когда мы создаем новый тип исключения, мы создаем новый класс на базе предка Exception. Согласно предыдущему, это будет выглядеть как:

Type

EMyException=class(Exception);

Класс Exception обладает некоторыми свойствами и методами, которые наследуются всеми его потомками. Основной метод класса Exception – это конструктор Create(<строка>), который создает исключение со строкой сообщения. Основное свойство – это Message, которое содержит строку сообщения.

Для инициализации исключения следует написать Raise и создать исключение, например,

If a1<0 Then

raise EMyException.Create(Величина a1<0);

В этом примере, если величина a1 окажется отрицательной, то инициализируется исключение EMyException с сообщением «Величина a1<0». Далее это исключение можно обработать или в текущем блоке программы при помощи операторов Try…Finally, Try…Except ( см. следующий раздел), или в главном модуле приложения в обработчике события onException невизуального компонента ApplicationEvents (см. описание примера 3.36).

3.9.2 Обработка исключений (Try, ApplicationEvents, Is)

Оператор TryFinally…end состоит из двух секций. В первой секции стоят операторы, правильность выполнения которых надо проверить, во второй – операторы завершения:

93

3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal

Try

<оператор 1.1>; <оператор 1.2>;

. . .

finally

<оператор 2.1>; <оператор 2.2>;

. . .

end;

В первую очередь выполняются операторы секции Try. Если при выполнении какого-либо из них произойдет исключительная ситуация, последующие операторы этой секции пропускаются и выполняются операторы секции Finally. Если исключение не возникает, то операторы секции Finally все равно выполняются после завершения секции Try.

Оператор TryExcept…end может состоять из двух или трех секций:

Try

<оператор 1.1>; <оператор 1.2>;

. . .

except

on <тип исключения 1> do <обработка данного типа исключения>; on <тип исключения 2> do <обработка данного типа исключения>;

. . .

<или «обычные» операторы:>

<оператор 2.1>; <оператор 2.2>;

. . .

[else {обработать исключения, не указанные в on do}

<оператор 3.1>; <оператор 3.2>;

. . .] end;

Впервую очередь выполняются операторы секции Try. Если при выполнении какого-либо из них произойдет исключительная ситуация, последующие операторы этой секции пропускаются и выполняются операторы секции Except. Если исключение не возникает, то операторы секций Except не выполняются.

Всекцию Except могут помещаться операторы определения типа и обработки возникшего исключения – ondo, и операторы, которые надо выполнить в случае любого типа исключения. Секция Else выполняется

94

3.9 ОБРАБОТКА ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ

когда исключительная ситуация не обработана операторами в ondo

секции Except.

Имейте ввиду, что при запуске приложения из среды Delphi её отладчик Debugger перехватывает исключения для собственной специфической обработки. Поэтому, проверять работоспособность собственных алгоритмов обработки исключений надо либо при запуске откомпилированного приложения из файла *.exe, или при отключенном отладчике – команда меню Tools→ Debugger Options→General→ убрать флаг в поле Integrated debugging. В противном случае Вам придётся при каждом исключении отвечать отладчику – “OK”, а для продолжения работы приложения – нажимать клавишу F9.

П р и м е р 3.35

// Блок N:

procedure TForm1.Button1Click(Sender: TObject); var X,a,b: Double;

begin a:=1.0e+300;

b:=1.0e-300; // или b:=0;

Try

X:=a/b; except

on EOverflow do MessageDlg('Переполнение в блоке N', mtWarning,[mbOK],0);

on EZeroDivide do MessageDlg('Деление на ноль в блоке N', mtWarning,[mbOK],0);

else

MessageDlg('Непредусмотренное исключение в блоке N', mtWarning,[mbOK],0);

end;

Form1.Edit1.Text:='X= '+FormatFloat('0.000E+0',X); end;

Для централизованной обработки всех исключений необходимо установить на главную форму компонент TApplicationEvents (страница Additional палитры компонент). У него есть событие onException, в обработчике которого можно проанализировать все исключени, возникающие в приложении. Процедура обработчика имеет локальный параметр E типа Exception, который содержит передаваемое в процедуру исключение. Именно этот параметр и надо обрабатывать.

95

3ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal

Пр и м е р 3.36

{Централизованная обработка исключений }

procedure EventsException(Sender: TObject; E: Exception);

var EMessage: String;

// Сообщение исключения

res: Word;

// Результат кнопки диалога MessageDlg

begin

 

EMessage:=E.Message;

 

If E is ENotSoBadError Then begin

res:=MessageDlg(EMessage+'Не очень плохая ситуация.' +' Продолжить вычисления?', mtInformation,[mbOK,mbCancel],0);

Case res of

1

{OK} : Exit;

// Продолжить работу приложения

2

{Cancel}: Halt;

// Прекратить работу приложения

end;

 

end

 

 

else If E is EBadError Then

begin

 

 

ShowMessage(EMessage+'Очень плохая ситуация.'

 

+' Приложение прекратит свою работу.');

 

Halt;

// Прекратить работу приложения

end

 

else {Показать и обработать стандартное исключение соответствующим методом компонента Application}

Application.ShowException(E);

end;

Данная процедура обрабатывает три типа исключений: два нестандартных

ENotSoBadError, EBadError и в последней части else – все стандартные.

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

96

3.10ПРЕДСТАВЛЕНИЕ РИСУНКОВ В DELPHI

3.10ПРЕДСТАВЛЕНИЕ РИСУНКОВ В DELPHI

3.10.1Компоненты для работы с графикой

В стандартную библиотеку Delphi входит несколько компонент, с помощью которых можно придать программе оригинальный вид. Это

TBevel, TImage, TPaintBox, TShape и другие. С первым из них мы уже познакомились в лабораторной работе 2. Прежде чем рассмотреть остальные, давайте обсудим общие принципы построения рисунков в среде

Delphi.

Необходимо различать рисование различных фигур при помощи пера (Pen), кисти (Brush) и шрифтов (Font) непосредственно программистом и прорисовку изображения формы операционной системой Windows, что делается автоматически, если окно формы создаётся или выходит на первый план, после того как его часть была закрыта другими окнами. При каждой прорисовке формы генерируется событие onPaint. Поэтому, рисование программистом на объекте-форме необходимо организовывать внутри обработчика данного события. Заметим, что рисование в обработчике события onCreate для формы бесполезно, т.к. на момент возникновения данного события форма ещё не создана.

Для немедленной прорисовки, т.е. для активизации события onPaint, необходимо выполнить метод Repaint. Не следует злоупотреблять этим методом, поскольку операции рисования относительно медленные, что может привести к заметной задержке в работе всего приложения. Если Вы хотите, чтобы рисунок изменялся с размерами формы, то необходимо обрабатывать событие onResize и перед перерисовкой Вашего рисунка очистить поверхность формы методом Refresh.

Теперь обсудим основные графические компоненты.

TImage – окно для вывода картинок и рисования на них. Он очень прост в использовании. Выберите данный компонент на странице Additional и поместите его в нужное место. Непосредственно картинка размещается через свойство Picture – контейнер для изображения, который в свою очередь является объектом класса TPicture. Картинка может быть в формате *.bmp (Bitmap – несжатая растровая графика), *.wmf или *.emf

(векторная графика Windows/Enhanced Metafile), *.ico (Icon) и *.jpeg

(сжатая растровая графика). Для работы с изображениями разных форматов в TImage существуют свойства, которые также являются самостоятельными компонентами, – Bitmap, Metafile, Icon. Мы их рассмотрим ниже.

Важными для TImage являются свойства Center и Stretch – оба имеют булевский тип. Если Center установлено в True, то центр изображения будет совмещаться с центром объекта TImage, иначе – изображение будет выровнено по левому верхнему краю. Если Stretch установлено в True, то

97

3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal

изображение будет сжиматься или растягиваться таким образом, чтобы заполнить весь объект TImage. Свойство AutoSize при значении True приводит размеры TImage к размерам размещенного в нем изображения.

Особое свойство-компонент Canvas – это холст для рисования. Посредством него можно добавлять свои рисунки к изображению, находящемуся в Picture в формате Bitmap. При рисовании посредством Canvas на объектах TImage, в действительности, происходит рисование на растровом изображении, находящимся в ОЗУ. При возникновении события onPaint компонент TImage просто копирует участок ОЗУ в видеопамять. Это существенно ускоряет процедуру прорисовки и делает её автоматической.

При проектировании следует помнить, что изображение, помещенное на какой-либо компонент во время дизайна (через инспектор объектов), включается в файл *.dfm и затем прикомпилируется к *.exe файлу. Поэтому такой *.exe файл может получиться достаточно большой. Как альтернативу можно рассмотреть загрузку картинки во время выполнения программы с помощью соответствующего метода очередного компонента.

TPicture – невизуальный контейнер рисунков общего типа TGraphic. У него есть два очень полезных метода, аналогичных компоненту TStrings (контейнер строк). Метод LoadFromFile загружает изображение из файла, например,

Image1.Picture.LoadFromFile(<имя файла>);

Метод SaveToFile сохраняет рисунок в файле, например,

Image1.Picture.SaveToFile(<имя файла>);

Кроме того, для копирования изображения между графическими компонентами, возможно, с необходимым преобразованием типа рисунка из

Metafile, Icon, Gif, Jpeg… в Bitmap, используется метод Assign, например,

Image1.Picture.Assign(Clipboard);

где Clipboard1 – это объект типа TClipboard «буфер обмена» из которого и копируется рисунок в Image1. Еще пример,

Image2.Picture.Assign(Image1.Picture);

– копирование рисунка из Image1 в Image2.

Строго говоря, непосредственно рисунок контейнера TPicture содержится в его свойстве Bitmap, Metafile и т.д. в зависимости от типа рисунка.

TBitmap, а также TMetafile, TIcon, TJpegImage2, TGraphic – это изображения в форматах *.bmp, *.emf, *.ico, *.jpeg соответственно. Эти невизуальные компоненты доступны только посредством написания кодов

1доступно через модуль Clipbrd

2доступно через модуль Jpeg

98

3.10 ПРЕДСТАВЛЕНИЕ РИСУНКОВ В DELPHI

программы (см. пример 3.39). Последний компонент TGraphic – это абстрактный тип изображения, применимый для любого допустимого формата. Напомним, что рисование в TImage всегда осуществляется в формате Bitmap. Чтобы рисовать, например, на jpeg-рисунке надо сначала его преобразовать в Bitmap-рисунок методом Assign:

Image1.Picture.Bitmap.Assign(Image1.Picture.Graphic);

Обратные преобразования (из Bitmap в другие изображения) делаются при помощи классов TMetafile, TIcon, TJpegImage и т.п. Вводится переменная для нового типа изображения, например,

Var IJ: TJpegImage;

IJ := TJpegImage.Create; {создаём требуемый объект}

IJ.Assign(Image1.Picture.Bitmap); {делаем преобразование}

TPaintBox – окно для рисования. Этот компонент находится на странице System палитры компонент. Никаких ключевых свойств кроме Canvas (см. следующий раздел) TPaintBox не имеет, собственно, этот объект является холстом для рисования, например, – различных графиков. В отличие от TImage, в компонент TPaintBox нельзя загружать готовые изображения. Кроме того здесь изображение не прорисовывается автоматически при выходе окна на передний план, поскольку изображение в TPaintBox не хранится в отдельной области ОЗУ (отсутствуют свойства типа Bitmap) для дублирования в видеопамять. Данный компонент кажется проще, чем TImage, но он и менее требователен к ресурсам ОЗУ. Целесообразно рисовать на холсте TPaintBox внутри обработчика события

onPaint.

TShape – находится на странице Additional палитры компонент. Он создает простейшие геометрические фигуры типа круга, квадрата и т.п. Вид объекта указывается в свойстве Shape (перечень возможных значений приведен в приложении 7). Свойство Pen определяет цвет и вид границы объекта. Brush задает цвет и вид заполнения объекта. Эти свойства можно устанавливать как во время дизайна интерфейса, так и во время выполнения программы. Свойства Brush и Pen также являются и самостоятельными компонентами.

TBrush – кисть, обладает набором свойств: Color – цвет заливки фигуры (см. приложение 7); Style – предопределенный стиль заливки (сплошной – bsSolid, без заливки – bsClear, диагональная штриховка – bsDiagCross… см. приложение 7). Полный перечень стилей можно получить через подсказку F1 среды Delphi.

99

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]