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

Мансуров. Основы программирования в среде Lazarus. 2010

.pdf
Скачиваний:
45
Добавлен:
27.04.2021
Размер:
6.3 Mб
Скачать

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

но возникновение исключений. После except следуют операторы, которые образуют секцию обработки исключений. Признаком конца секции служит ключевое слово end. Внутри секции программист указывает классы исключе-

ний (говорят еще типы исключений) после слова on, а затем после ключевого слова do оператор обработки исключения, причем оператор может быть со-

ставным. После необязательного else следуют операторы обработки исклю-

чений, не вошедшие в перечень on. Если программисту нужно только устано-

вить сам факт исключения, независимо от типа, то он может просто записать обработчик исключения после слова except.

Вторая конструкция имеет вид:

try

<Потенциально "опасные" операторы, при выполнении которых могут возникнуть исключительные ситуации >

finally

<операторы, которые должны быть выполнены в любом случае, незави-

симо от того, произошло исключение или нет >

end;

В чем их различие? В конструкции try..except если при выполнении операторов секции try возникло исключение, то управление передается в сек-

цию except, где и происходит обработка исключения. Если же исключения не произошло, то операторы блока except просто пропускаются. В конструкции try..finally операторы будут выполнены независимо от того, произошло исключение или нет.

Рассмотрим пример:

try

num:=StrToInt(Stroka);

521

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

except

on EConvertError do

ShowMessage('Ошибка преобразования строки в целое число');

end;

Здесь сообщение будет выведено только в том случае, когда невозможно преобразование строки символов в целое число, то есть когда возникнет ис-

ключение EConvertError.

Конструкции try..except и try..finally могут быть вложены друг в друга на неограниченную глубину. Рассмотрим реализацию примера с файлом.

Procedure Test; var

F: TextFile; number: integer; s: string;

begin

AssignFile(F, 'Data.txt');

Rewrite(F);

s:= '12#4';

// В файл намеренно записывается

Writeln(F, s);

// ошибочная строка символов

Reset(F);

 

try

// начало секции (блока) try..except

Readln(F, s);

 

try

// начало секции try..finally

number:= StrToInt(s);

finally

CloseFile(F); // эти два оператора будут выполнены

522

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

DeleteFile('Data.txt'); // в любом случае

end; // конец секции try..finally

except

on EConvertError do

ShowMessage('Ошибка преобразования'); end; // конец секции try..except

end;

Вернемся к примеру, в котором осуществляется ввод двух целых чисел и выполняются четыре арифметических действия (сложение, вычитание, умно-

жение и деление нацело), рис. 6.30. Модифицируем программу, добавив в него обработку исключений. Перепишите обработчики события OnKeyPress для

LabeledEdit1 и событий OnClick кнопок SpeedButton1, SpeedButton2, SpeedButton3 и SpeedButton4 в виде:

procedure TForm1.LabeledEdit1KeyPress(Sender: TObject; var Key: char);

begin

if Key = #13 then begin

try StrToInt(LabeledEdit1.Text);

except

on EConvertError do begin

ShowMessage('Ошибка преобразования! Вероятно, ' +

'Вы ошиблись при вводе числа');

exit;

end;

523

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

end;

LabeledEdit2.SetFocus; SpeedButton1.Down:= false; SpeedButton2.Down:= false; SpeedButton3.Down:= false; SpeedButton4.Down:= false; exit;

end;

end;

procedure TForm1.SpeedButton1Click(Sender: TObject); begin

try LabeledEdit3.Text:=IntToStr(StrToInt(LabeledEdit1.Text)

+ StrToInt(LabeledEdit2.Text));

except

on EConvertError do begin

ShowMessage('Ошибка преобразования! Вероятно, ' + 'Вы ошиблись при вводе второго числа');

exit;

end;

end;

StatusBar1.SimpleText:= 'Сложение';

LabeledEdit1.SetFocus;

LabeledEdit1.SelectAll;

end;

procedure TForm1.SpeedButton2Click(Sender: TObject);

524

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

begin try

LabeledEdit3.Text:=IntToStr(StrToInt(LabeledEdit1.Text)

- StrToInt(LabeledEdit2.Text));

except

on EConvertError do begin

ShowMessage('Ошибка преобразования! Вероятно, ' + 'Вы ошиблись при вводе второго числа');

exit;

end;

end;

StatusBar1.SimpleText:= 'Вычитание';

LabeledEdit1.SetFocus;

LabeledEdit1.SelectAll;

end;

procedure TForm1.SpeedButton3Click(Sender: TObject); begin

try LabeledEdit3.Text:=IntToStr(StrToInt(LabeledEdit1.Text)

* StrToInt(LabeledEdit2.Text));

except

on EConvertError do begin

ShowMessage('Ошибка преобразования! Вероятно, ' +

'Вы ошиблись при вводе второго числа');

exit;

end;

525

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

end;

StatusBar1.SimpleText:= 'Умножение';

LabeledEdit1.SetFocus;

LabeledEdit1.SelectAll;

end;

procedure TForm1.SpeedButton4Click(Sender: TObject); begin

try LabeledEdit3.Text:=IntToStr(StrToInt(LabeledEdit1.Text)

div StrToInt(LabeledEdit2.Text));

except

on EConvertError do begin

ShowMessage('Ошибка преобразования! Вероятно, ' + 'Вы ошиблись при вводе второго числа');

exit;

end;

on EDivByZero do begin

ShowMessage('Ошибка! Произошло деление на ноль. Вероятно, ' + 'Вы ошиблись при вводе второго числа');

exit;

end;

end;

StatusBar1.SimpleText:= 'Деление нацело';

LabeledEdit1.SetFocus;

LabeledEdit1.SelectAll;

end;

526

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

Теперь при вводе недопустимого символа для целого числа, а также при вводе числа 0 в качестве второго операнда программа перехватывает исключе-

ния и реагирует соответствующим образом.

Имейте в виду, если вы запускаете программу из среды Lazarus, то исклю-

чения будет перехватывать отладчик. Поэтому лучше запускать программу из командной строки или в настройках окружения для отладчика добавьте нужные вам типы исключений в список игнорирования.

Обработку исключений вполне можно применять и в консольных прило-

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

используя механизм исключений.

program int_operations_control; {$mode objfpc}{$H+}

uses

CRT, FileUtil, SysUtils; var

A, B, C: integer; begin

writeln(UTF8ToConsole('Введите два числа')); readln(A, B);

writeln('A= ', A, ' B= ', B); C:= A + B;

writeln(UTF8ToConsole('Демонстрация сложения, C= '), C); C:= A * B;

writeln(UTF8ToConsole('Демонстрация умножения, C= '), C); try

C:= A div B;

writeln(UTF8ToConsole('Демонстрация деления нацело, C= '),

C);

527

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

except

on EDivByZero do begin

writeln(UTF8ToConsole('Ошибка!! Деление на ноль.')); writeln(UTF8ToConsole('Нажмите любую клавишу')); readkey;

exit;

end;

end;

C:= A mod B;

writeln(UTF8ToConsole('Остаток от деления, C= '), C); C:= A - B;

writeln(UTF8ToConsole('Демонстрация вычитания, C= '), C); writeln(UTF8ToConsole('Нажмите любую клавишу')); readkey;

end.

Сравните эту программу с программой из 2.1.25.

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

программа перешла непосредственно к обработке данных – идут вычисления,

происходит чтение и запись в файлы, обращения к различным внешним уст-

ройствам и т.д. На этапе же ввода данных, когда пользователь в режиме диало-

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

528

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

нию кода. Гораздо разумнее и эффективней при вводе данных просто не давать пользователю совершить ошибку. Например, если пользователь должен вво-

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

просто этот символ игнорировать.

Для этого удобнее использовать другую разновидность компонента TEdit

TMaskEdit из страницы Additional.

6.3.7.1. Компонент TMaskEdit

В этом компоненте имеется свойство EditMask, с помощью которого можно задать маску ввода. Маска это некий шаблон, задающий какие символы может вводить пользователь в окне ввода. Недопустимые символы игнориру-

ются. Маска состоит из трех частей, между которыми ставится точка с запятой

(;). В первой части маски – шаблоне записываются символы (табл. 6.2), кото-

рые указывают какие символы можно вводить в каждой позиции.

Таблица 6.2

Символ

Шаблон ввода

Означает, что в EditText недостающие символы предваряются

!пробелами. В случае отсутствия символа пробелы размещаются в конце.

0 Означает, что в данной позиции должна быть цифра.

9 Означает, что в данной позиции может быть цифра или ничего.

#Означает, что в данной позиции может быть цифра, знак « + », знак «-» или ничего.

Далее через точку с запятой (;) записывается 1 или 0 в зависимости от того,

надо или нет, чтобы символы, добавляемые маской, включались в свойство

Text компонента. В третьей части маски указывается символ-заполнитель, ис-

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

тановить нужную маску можно прямо в свойстве EditMask, введя необходи-

мые символы маски или в редакторе масок, открыть который можно нажав

529

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

кнопку с троеточием, рис. 6.33.

Рис. 6.33. Окно редактора масок

Прочитать результат ввода можно или в свойстве Text, которое, в зависи-

мости от вида второй части маски, включает или не включает в себя символы маски, или в свойстве EditText, содержащем введенный текст вместе с сим-

волами маски.

Итак, давайте применим для нашего примера компонент TMaskEdit.

Удалите из формы LabeledEdit1 и LabeledEdit2. Перенесите на их ме-

сто два компонента TMaskEdit. Также вставьте в форму два компонента

TLabel. В общем, восстановите внешний вид формы как на рисунке 6.30.

Установите следующие свойства MaskEdit1:

AutoSelect = true

EditMask = #9999;0;

TabOrder = 0

свойство Text оставьте пустым.

В качестве символа заполнителя в окошке "Символы для пробелов" в ре-

дакторе масок введите пробел вместо знака подчеркивания.

Установите свойства MaskEdit2:

530