Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
osnovy_programmirovanija_v_srede_lazarus.pdf
Скачиваний:
185
Добавлен:
18.03.2015
Размер:
6.53 Mб
Скачать

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

____________________________________________________________________

Это будет отличнейшей тренировкой для вас!

Ая, с вашего позволения, перейду к рассмотрению других вопросов.

6.3.11Организация меню. Механизм действий - Actions

6.3.11.1. Компонент TMainMenu

Рассмотрим способы создания и организации меню. В меню пользователь выбирает не данные, а возможные действия. Таким образом, меню это специ-

альный механизм, позволяющий пользователю внутри вашего приложения вы-

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

Для создания главного меню используется компонент TMainMenu (вклад-

ка Standard). Компонент не визуальный. Пункты меню содержатся в свойст-

ве Items. Чтобы начать формирование пунктов меню достаточно дважды щелкнуть по компоненту на форме или нажать на кнопку с многоточием в свойстве Items компонента в инспекторе объектов. Откроется специальный редактор меню, рис. 6.82.

Рис. 6.82. Редактор меню

В инспекторе объектов в свойство Caption введите имя пункта меню.

Чтобы создать следующий пункт меню или подменю, установите курсор на те-

717

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

____________________________________________________________________

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

ню", рис. 6.84.

Рис. 6.83. Контекстное меню редактора

Рис. 6.84. Пример создания подменю

Lazarus предоставляет возможность при создании меню применить шабло-

ны меню. Имеется три стандартных шаблона для меню "Файл", "Правка" и "Справка", рис. 6.85.

718

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

____________________________________________________________________

Рис. 6.85. Шаблоны меню

При создании меню имеется возможность вставки рядом с текстом пункта меню пиктограммы. Для этого поместите на форму компонент

TImageList, заполните его соответствующими рисунками. Затем в

TMainMenu в свойстве Images укажите имя TImageList в программе. А

при создании подпункта меню в свойстве ImageIndex укажите индекс соот-

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

Также вы можете добавить горячие клавиши для данного пункта меню.

Для этого служит свойство Shortcut. Вы можете прямо ввести нужное соче-

тание клавиш в поле ввода этого свойства или нажав на кнопку с многоточием,

выбрать нужное сочетание из появившегося редактора выбора сочетаний кла-

виш, рис. 6.86.

Рис. 6.86. Установка сочетаний клавиш

Для создания разделительной линии между пунктами меню достаточно создать новый элемент и в свойство Caption ввести знак "-".

719

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

____________________________________________________________________

Попробуйте реализовать пункт меню "Файл" Lazarus. Рисунки вы можете найти в папке установки Lazarus (подпапка Images), рис. 6.87.

Рис. 6.87. Пример создания меню

При этом вместо безликих имен пунктов меню (в программе) типа MenuItem1, MenuItem2 и т.д. желательно присваивать им осмысленные имена, на-

пример MCreateModule, MCreateForm.

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

достаточно просто дважды щелкнуть по этому пункту.

Еще с первой главы за мной тянется один должок. В 1.3.3. мы с вами рас-

сматривали метод наименьших квадратов, а программу мы так и не написали.

Но, как говорится, всему свое время. И вот это время наступило. Приступим к реализации этого метода.

720

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

____________________________________________________________________

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

нента является Series – наборы данных (серии), на основе которых и строятся графики или диаграммы. Если дважды щелкнуть по компоненту, размещенному на форме, то мы попадем в редактор серий, рис. 6.88.

Рис. 6.88. Редактор серий

Существуют разные типы Series для построения разных типов графиков или диаграмм, например Line series – для построения линий (графиков),

Pie series – для построения круговых диаграмм и т.д. Выберите тип серии

Line series. В инспекторе объектов появится объект ChartLineSeries1

типа TLineSeries.

Рис. 6.89. Создание объекта типа TLineSeries

Создать программно объект типа TLineSeries можно оператором

Chart1LineSeries1:= TLineSeries.Create(Chart1);

721

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

____________________________________________________________________

Для добавления серии в TChart существует метод

procedure AddSeries(ASeries: TBasicChartSeries);

Добавление точек в объект типа TLineSeries производится с помощью

функции

function AddXY(X, Y: Double): Integer;

Свойство ShowPoints: boolean позволяет показывать или не показы-

вать точки на графике.

Свойство SeriesColor: TColor позволяет указать цвет линии.

Чтобы вывести график функции, например, sin(x) можно написать сле-

дующую процедуру:

procedure Plot_sin; var

i, n: integer; Chart1LineSeries1: TLineSeries;

begin

n:= 100;

Chart1LineSeries1:= TLineSeries.Create(Chart1); Chart1LineSeries1.SeriesColor:= clRed; Chart1LineSeries1.ShowPoints:= false; Chart1.AddSeries(Chart1LineSeries1); Chart1.Title.Visible:= true; Chart1.Title.Text.Text:= 'График функции sin(x)'; for i:= 0 to n - 1 do

Chart1LineSeries1.AddXY(i*Pi*0.02,

722

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

____________________________________________________________________

sin(i*Pi*0.02));

end;

Итак, давайте начнем реализацию метода наименьших квадратов. Создайте новый проект, поместите на форму компоненты TMainMenu, TOpenDialog и TChart, как показано на рис. 6.90. Меню программы должно состоять из сле-

дующих пунктов:

Файл

Определение коэффициентов полинома Графики

В свою очередь, меню "Файл" должен состоять из подпунктов "Открыть" и

"Выход". Меню "Определение коэффициентов полинома" должна содержать пункт "Вычислить". И меню "Графики" должен содержать пункты "График экспериментальных точек" и "Подобранная кривая", рис.6.91.

Присвойте имена меню в программе как показано на рис. 6.92.

Вставим в пункты меню рядом с их текстами пиктограммы. Для этого по-

местите на форму компонент TImageList и заполните его подходящими значками. В свойстве Images MainMenu1 укажите имя TImageList. Затем для каждого пункта меню укажите соответствующие индексы в свойствах

ImageIndex.

723

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

____________________________________________________________________

Рис. 6.90. Форма приложения

Рис. 6.91. Создание меню программы с помощью редактора меню

Рис. 6.92. Имена меню в программе

Код программы:

724

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

____________________________________________________________________

unit unit1;

{$mode objfpc}{$H+} interface

uses

Classes, SysUtils, LResources, Forms, Controls,

Graphics, Dialogs, ExtCtrls, TAGraph, TASeries,

Buttons, StdCtrls, Menus, FileUtil;

type

{ TForm1 }

TForm1 = class(TForm)

Chart1: TChart;

MainMenu1: TMainMenu;

MCalculate: TMenuItem;

Menu_File: TMenuItem;

Menu_Calculate: TMenuItem;

Menu_Grafic: TMenuItem;

Menu_Open: TMenuItem;

Menu_Exit: TMenuItem;

Menu_Exp: TMenuItem;

Menu_Curve: TMenuItem;

OpenDialog1: TOpenDialog;

procedure FormCreate(Sender: TObject); procedure Menu_ExpClick(Sender: TObject); procedure Menu_CurveClick(Sender: TObject); procedure Menu_OpenClick(Sender: TObject); procedure MCalculateClick(Sender: TObject);

private

{ private declarations }

725

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

____________________________________________________________________

public

{ public declarations }

end;

// Процедура решения СЛАУ методом Гаусса

procedure gauss(vector: array of real; b: array of real;

var x: array of real; n: byte;

var solve: byte);

//n - размерность системы,

//solve=0, если решение единственное,

//solve=1, если система не имеет решения,

//solve=2, если система имеет бесконечное количество решений,

//Функция, подбираемая методом

//наименьших квадратов

function fx(t: real): real;

// Функция возведения в степень

function stepen( x: real; n: byte): real;

var

Form1: TForm1; n: byte;

x1, y1: real;

x, y, z: array of real; Fname: string;

implementation

function fx(t: real): real;

726

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

____________________________________________________________________

begin

Result:= z[0] + z[1]*t + z[2]*t*t + z[3]*t*t*t + z[4]*sqr(sqr(t));

end;

function stepen( x: real; n: byte): real; var

i: integer; begin

Result:= 1;

for i:= 1 to n do Result:= Result*x;

end;

// Реализация метода Гаусса

procedure Gauss(vector: array of real; b: array of real; var x: array of real; n: byte;

var solve: byte);

var

a: array of array of real; { матрица коэффициентов системы,

двумерный динамический массив}

i, j, k, p, r: integer;

m, s, t: real;

begin

SetLength(a, n, n); // установка фактического размера массива

{ Преобразование одномерного массива в двумерный }

k:=0;

for i:=0 to n-1 do

for j:=0 to n-1 do

727

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

____________________________________________________________________

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; // в алгоритме используется буква l, но она похожа на 1

// Поэтому используем идентификатор p 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;

728

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

____________________________________________________________________

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;

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;

solve:= 0; end

else

if b[n-1] = 0 then begin

MessageDlg('Система имеет бесконечное ' +

729

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

____________________________________________________________________

'количество решений', mtInformation,[mbOK], 0); solve:= 2;

end else begin

MessageDlg('Система не имеет решений',

mtInformation,[mbOK], 0);

solve:= 1; end;

{ освобождение памяти,

распределенной для динамического массива }

a:=nil;

end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject); begin

Chart1.Title.Text.Text:='Метод наименьших квадратов'; MCalculate.Enabled:= false;

Menu_Exp.Enabled:= false;

Menu_Curve.Enabled:= false;

end;

procedure TForm1.Menu_ExpClick(Sender: TObject);

{Процедура вывода графика экспериментальных

данных по точкам}

var

i: integer;

730

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

____________________________________________________________________

gr1: TLineSeries; begin

Chart1.Visible:= true;

gr1:= TLineSeries.Create(Chart1); Chart1.AddSeries(gr1);

for i:= 0 to n - 1 do gr1.AddXY(x[i], y[i]);

end;

procedure TForm1.Menu_CurveClick(Sender: TObject);

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

var

i: integer;

gr1, gr2: TLineSeries; begin

Chart1.Visible:= true;

gr1:= TLineSeries.Create(Chart1); gr1.ShowPoints := true; // график с точками gr1.ShowLines := false; // не соединять точки линиями

Chart1.AddSeries(gr1);

gr2:= TLineSeries.Create(Chart1); gr2.ShowLines := true; Chart1.AddSeries(gr2);

for i:= 0 to n - 1 do gr1.AddXY(x[i], y[i]);

731

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

____________________________________________________________________

for i:= 0 to n - 1 do gr2.AddXY(x[i], fx(x[i]));

end;

procedure TForm1.Menu_OpenClick(Sender: TObject);

// процедура выбора, открытия и чтения файла данных var

f: TextFile; i: integer;

begin

if OpenDialog1.Execute then Fname:= OpenDialog1.FileName

else exit;

Fname:= UTF8ToSys(Fname); //преобразование в системную кодировку

AssignFile(f, Fname);

Reset(f);

// отключение контроля ошибок ввода/вывода

{$I-}

// чтение количества экспериментальных точек

Readln(f, n);

if IOResult <> 0 then

begin

ShowMessage('Ошибка при чтении из файла!');

exit;

end;

// распределение памяти под динамические массивы

SetLength(x, n);

SetLength(y, n);

for i:= 0 to n - 1 do

732

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

____________________________________________________________________

begin

read(f, x[i]);

if IOResult <> 0 then begin

ShowMessage('Ошибка при чтении из файла!'); exit;

end;

end;

for i:= 0 to n - 1 do begin

read(f, y[i]);

if IOResult <> 0 then begin

ShowMessage('Ошибка при чтении из файла!'); exit;

end;

end; {$I+}

CloseFile(f);

MCalculate.Enabled:= true;

end;

procedure TForm1.MCalculateClick(Sender: TObject); var

i, j, k, l: integer;

b, vector: array of real; s: real;

solve: byte; begin

SetLength(z, 5);

733

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

____________________________________________________________________

SetLength(b, 5); SetLength(vector, 25); j:= 0;

for k:= 0 to 4 do for l:= 0 to 4 do begin

s:= 0;

for i:= 0 to n - 1 do

s:= s + stepen(x[i], k + l); vector[j]:= s;

j:= j+1; end;

for k:= 0 to 4 do begin

s:= 0;

for i:= 0 to n - 1 do

s:= s + y[i]*stepen(x[i], k); b[k]:= s;

end;

// решение СЛАУ

gauss(vector, b, z, 5, solve); if solve = 0 then

begin

Menu_Exp.Enabled:= true;

Menu_Curve.Enabled:= true;

end;

end; initialization

{$I unit1.lrs}

734

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

____________________________________________________________________

end.

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

тов системы мы сначала преобразовывали в одномерный динамический массив,

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

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

Поэтому в программе метода наименьших квадратов в процедуре

MCalculateClick формируется одномерный динамический массив vector,

который на самом деле является матрицей коэффициентов системы. Его мы и передаем (вместе с вектором свободных членов) в процедуру Gauss.

Перед пуском программы подготовьте в любом текстовом редакторе файл следующего вида:

Рис. 6.93. Файл данных

Файл имеет следующую структуру. Первая строка содержит количество точек. Вторая строка содержит значения Zi, третья строка содержит значения

Pi.

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

ми пункты меню "Вычислить", "График экспериментальных точек" и "Подобранная кривая" необходимо сделать недоступными. После загрузки

735

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