Мансуров. Основы программирования в среде Lazarus. 2010
.pdfГлава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
m, s, t: real; begin
try
SetLength(a, n, n); {установка фактического размера массива Преобразование одномерного массива в двумерный} k:= 1;
for i:= 0 to n - 1 do for j:= 0 to n - 1 do begin
a[i, j]:= vector[k]; k:= k + 1;
end;
for k:= 0 to n - 2 do begin
for i:= k + 1 to n - 1 do begin
if (a[k, k]= 0) then begin
{перестановка уравнений} p:= k;
for r:= i to n - 1 do begin
if abs(a[r, k]) > abs(a[p, k]) then p:= r; end;
if p <> k then begin
for j:= k to n - 1 do begin
t:= a[k, j];
a[k, j]:= a[p, j]; a[p, j]:= t;
end;
t:= b[k]; b[k]:= b[p]; b[p]:= t;
end;
end; // конец блока перестановки уравнений m:= a[i, k] / a[k, k];
a[i, k]:= 0;
for j:= k + 1 to n - 1 do begin
a[i, j]:= a[i, j] - m * a[k, j]; end;
611
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
b[i]:= b[i] - m * b[k]; end;
end;
{Проверка существования решения} if a[n - 1, n - 1] <> 0 then begin
x[n - 1]:= b[n - 1] / a[n - 1, n - 1]; for i:= n - 2 downto 0 do
begin s:= 0;
for j:= i + 1 to n - 1 do begin
s:= s - a[i, j] * x[j]; end;
x[i]:= (b[i] + s) / a[i, i]; end; Memo1.Lines.Add('Решение:'); for i:= 0 to n - 1 do
Memo1.Lines.Add('x' + IntToStr(i + 1) + '=' + FloatToStr(x[i]));
end else
if b[n - 1] = 0 then Memo1.Lines.Add('Система уравнений' +
' не имеет решения.')
else
Memo1.Lines.Add('Система уравнений' +
' имеет бесконечное множество решений.');
except
on EInvalidOP do
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
on EMathError do
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
on EZeroDivide do
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
on EOverflow do
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
on EUnderflow do
612
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
on EAccessViolation do
Memo1.Lines.Add('Неправильные данные. Система уравнений' + ' не имеет решения.');
end;
a:= nil; // освобождение памяти end;
procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word; Shift:TShiftState);
begin
if (Key = VK_Return) then begin
if (StringGrid1.Col >= n) then begin
StringGrid1.Row:= StringGrid1.Row + 1; StringGrid1.Col:= 0;
Key:= 0; end;
end;
end;
procedure TForm1.FormShow(Sender: TObject); begin
StringGrid1.ColCount:= 1;
StringGrid1.RowCount:= 1; Edit1.SetFocus; Button3.Visible:= true; Button4.Visible:= false;
end;
procedure TForm1.Button1Click(Sender: TObject); begin
Memo1.Clear;
StringGrid1.Clean; StringGrid1.ColCount:= 1; StringGrid1.RowCount:= 1; Edit1.Clear; Edit1.SetFocus; Button3.Visible:= true; Button4.Visible:= false;
end;
procedure TForm1.Button2Click(Sender: TObject); begin
{освобождение памяти,
613
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
распределенной для динамических массивов} a:= nil;
vector:= nil; x:= nil;
b:= nil; Close();
end;
procedure TForm1.Button3Click(Sender: TObject); begin
Edit1.SetFocus;
if Length(Edit1.Text) = 0 // если пустая строка then exit;
n:= StrToInt(Edit1.Text); StringGrid1.ColCount:= n + 1; StringGrid1.RowCount:= n ; Stringgrid1.SetFocus; Button3.Visible:= false; Button4.Visible:= true;
end;
procedure TForm1.Button4Click(Sender: TObject); begin
if (StringGrid1.Col >= n) then begin
StringGrid1.Row:= StringGrid1.Row + 1; StringGrid1.Col:= 0;
end else
StringGrid1.Col:= StringGrid1.Col+1; end;
procedure TForm1.Button5Click(Sender: TObject); var i, j, k, code:integer;
begin
{Установка реальных размеров динамических массивов} SetLength(a, n, n);
SetLength(vector, n * n); SetLength(b, n); SetLength(x, n);
for j:= 0 to n - 1 do for i:= 0 to n - 1 do begin
val(StringGrid1.Cells[i, j], a[i, j], code); if code <> 0 then
begin
614
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
ShowMessage('Ошибка при вводе коэффициентов матрицы'); StringGrid1.SetFocus;
exit;
end;
end;
for j:= 0 to n - 1 do begin
val(StringGrid1.Cells[n, j], b[j], code); if code <> 0 then
begin
ShowMessage('Ошибка при вводе свободных членов'); StringGrid1.SetFocus;
exit;
end;
end;
code:=0;
{Преобразование двумерного массива в одномерный} k:= 1;
for j:= 0 to n - 1 do for i:= 0 to n - 1 do begin
vector[k]:= a[i, j]; k:= k + 1;
end;
{Вызов процедуры решения системы линейных алгебраических уравнений методом Гаусса}
Gauss(vector, b, x, n); end;
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
begin
if Key = #13 then begin
if Length(Edit1.Text) = 0 // если пустая строка then exit;
n:=StrToInt(Edit1.Text); StringGrid1.ColCount:= n + 1; StringGrid1.RowCount:= n ; Stringgrid1.SetFocus;
exit;
end;
{разрешаем только цифры, знак минус и кл. BackSpace} if not (Key in ['0' .. '9', #8])
615
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
then begin
Key:= #0; exit;
end;
end; initialization
{$I Unit1.lrs} end.
В программе пользователь может вводить коэффициенты и редактировать их прямо в TStringGrid. После нажатия кнопки "Решить" данные из
TStringGrid преобразуются в числовое представление и записываются в ди-
намические массивы a – матрица коэффициентов системы, b – вектор свобод-
ных членов. Далее осуществляется вызов процедуры Gauss()решения систе-
мы линейных алгебраических уравнений методом Гаусса, которая практически не отличается от консольного варианта. Если решение системы существует, по-
лученный вектор x[x1, x2, . . . , xn] преобразуется в строку и выводится на экран.
Для контроля ввода данных в Edit1 мы использовали метод, применен-
ный нами в 6.3.7.1. Для контроля ввода в StringGrid1 функцию Val(), а
при вычислениях применили механизм исключений.
6.3.10.3. Компоненты выбора
В этих компонентах можно организовать выбор каких-то элементов из списка. Весь список содержится в свойстве Items и имеет тип TString. Эле-
ментами списка являются строки. Строки нумеруются, начиная с нуля. Доступ к строке осуществляется с помощью указания индекса элемента в свойстве
Items, например Items[k] или свойства Items.Strings, например
Items.Strings[k].
Компонент TListBox
Рассмотрим компонент TListBox. Он расположен на странице
616
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
Standard. Основные свойства компонента:
MultiSelect – признак множественного выбора. Если MultiSelect = true, то разрешается выбор одновременно нескольких элементов.
ExtendedSelect – если ExtendedSelect= true и MultiSelect= true, то выбор нескольких элементов можно производить стандартным спосо-
бом, т.е. при нажатой клавише Shift можно выбрать несколько элементов,
расположенных подряд, а при нажатой клавише Ctrl выбрать элементы в произвольном порядке.
Count – общее количество элементов в компоненте.
ItemIndex – индекс выбранного элемента (при MultiSelect= false).
Если выбрано несколько элементов (MultiSelect= true), то содержит ин-
декс элемента, на котором установлен фокус.
Selected[i] – если выбран элемент с индексом i, то значение этого свой-
ства равно true.
Sorted – если равно true, то элементы компонента автоматически сорти-
руются.
Рассмотрим несколько примеров для того, чтобы освоить простейшую тех-
нику работы с этим компонентом. Поместите на форму два компонента
TListBox и три кнопки, так как показано на рис. 6.61.
Заполним программно ListBox1 содержимым текстового файла, в кото-
ром содержатся фамилии, допустим студентов. Затем будем просто помещать выбранные элементы в ListBox2. Сначала реализуем выбор одиночного эле-
мента.
617
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
Рис. 6.61. Форма приложения
Вот код этой программы:
unit Unit1;
{$mode objfpc}{$H+} interface
uses
Classes, SysUtils, FileUtil, LResources, Forms,
Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
ListBox1: TListBox;
ListBox2: TListBox;
procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject);
618
Глава 6 Программирование приложений с графическим интерфейсом
____________________________________________________________________
procedure FormCreate(Sender: TObject); private
{private declarations } public
{public declarations } end;
var
Form1: TForm1; implementation { TForm1 }
procedure TForm1.Button2Click(Sender: TObject); begin
with ListBox1 do begin
if ItemIndex >= 0 then ListBox2.Items.Add(Items[ItemIndex]);
end;
end;
procedure TForm1.Button1Click(Sender: TObject); begin
ListBox2.Clear;
end;
procedure TForm1.Button3Click(Sender: TObject); begin
Close;
end;
procedure TForm1.FormCreate(Sender: TObject); var
619
6.3 Визуальное программирование в среде Lazarus
____________________________________________________________________
tfile: TStringList; str: string;
begin
tfile:= TStringList.Create; tfile.LoadFromFile('List.txt'); str:= tfile.Text;
{$IFDEF WINDOWS}
str:= SysToUTF8(str); // преобразование в кодировку UTF-8
{$ENDIF}
with ListBox1 do begin
Items.Text:= str; end;
tfile.Free;
end; initialization
{$I unit1.lrs} end.
Если установить в ListBox2 свойство Sorted = true, то элементы будут выведены в отсортированном виде. При добавлении нового элемента, он будет помещен в нужное место автоматически.
В этой реализации, если при одном и том же выбранном элементе нажать на кнопку "Копировать" несколько раз, то этот элемент попадет в ListBox2
также несколько раз, т.е. строки в ListBox2 окажутся не уникальными.
Чтобы элементы в ListBox2 не повторялись, напишем функцию, кото-
рая проверяет не содержится ли уже этот элемент в ListBox2. Если такой элемент имеется, функция возвращает true, если нет, то false.
620