По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. |
Графика в Lazarus
Данная глава посвящена графическим средствам языка. Рассмотрены основные процедуры и функции работы с графикой. Приведён пример построения графика функции.
10.1 Средства рисования в Lazarus
При разработке проекта, в котором можно рисовать, в распоряжении программиста находится полотно (холст) — свойство Canvas, карандаш — свойство Pen, и кисть — свойство Brush.
Свойством Canvas обладают следующие компоненты:
- форма (класс Tform);
- таблица (класс TSringGrid);
- растровая картинка (класс Timage);
- принтер (класс TPrinter).
При рисовании компонента, обладающего свойством Canvas, сам компонент рассматривается как прямоугольная сетка, состоящая из отдельных точек, называемых пикселями. Положение пикселя характеризуется его вертикальной (X) и горизонтальной (Y) координатами. Левый верхний пиксель имеет координаты (0,0). Вертикальная координата возрастает сверху вниз, горизонтальная — слева направо. Общее количество пикселей по вертикали определяется свойством Height, а по горизонтали — свойством Weight. Каждый пиксель может иметь свой цвет. Для доступа к любой точке полотна используется свойство Pixels[X,Y]:TColor. Это свойство определяет цвет пикселя с координатами X(integer), Y(integer).
Изменить цвета любого пикселя полотна можно с помощью следующего оператора присваивания:
Компонент. Canvas. Pixels [X,Y] : = Color;
где Color — переменная или константа типа Tcolor.
Константа | Цвет | Константа | Цвет |
---|---|---|---|
clBlack | Чёрный | clSilve | Серебристый |
clMaroon | Каштановый | clRed | Красный |
clGreen | Зелёный | clLime | Салатовый |
clOlive | Оливковый | clBlue | Синий |
clNavy | Тёмно-синий | clFuchsia | Ярко-розовый |
clPurple | Розовый | clAqua | Бирюзовый |
clTeal | Лазурный | clWhite | Белый |
clGray | Серый |
Определены следующие константы цветов (табл. 10.1).
Цвет любого пикселя можно получить с помощью следующего оператора присваивания:
Color :=Компонент. Canvas. Pixels [X,Y ];
где Color — переменная типа Tcolor.
Класс цвета точки Tcolor определяется как длинное целое longint. Переменные этого типа занимают в памяти четыре байта. Четыре байта переменных этого типа содержат информацию о долях синего (B), зелёного (G) и красного (R) цветов и устроены следующим образом: $00BBGGRR.
Для рисования используются методы класса TСanvas, позволяющие изобразить фигуру (линию, прямоугольник и т. д.) или вывести текст в графическом режиме, и три класса, определяющие инструменты вывода фигур и текстов:
- TFont (шрифты);
- TPen (карандаш, перо);
- TBrush (кисть).
Класс TFONT. Можно выделить следующие свойства соответствующего объекта Canvas.TFont:
- Name (тип string) — имя используемого шрифта.
- Size (тип integer) — размер шрифта в пунктах (points). Пункт — это единица измерения шрифта, равная 0,353 мм или 1/72 дюйма.
- Style — стиль начертания символов, который может быть обычным, полужирным (fsBold), курсивным (fsItalic), подчёркнутым (fsUnderline) и перечёркнутым (fsStrikeOut). В программе можно комбинировать необходимые стили, например, чтобы установить стиль "полужирный курсив" необходимо написать следующий оператор: Объект. Canvas. Font. Style : = [ fsItalic, fsBold ]
- Color (тип Tcolor) — цвет символов.
- Charset (тип 0..255) — набор символов шрифта. Каждый вид шрифта, определяемый его именем, поддерживает один или более наборов символов. В табл. 10.2 приведены некоторые значения Charset.
Константа | Значение | Описание |
---|---|---|
ANSI_CHARSET | 0 | Символы ANSI |
DEFAULT_CHARSET | 1 | Задаётся по умолчанию. Шрифт выбирается только по его имени Name и размеру Size. Если описанный шрифт недоступен в системе, он будет заменён другим |
SYMBOL_CHARSET | 2 | Стандартный набор символов |
MAC_CHARSET | 77 | Символы Macintosh |
GREEK_CHARSET | 161 | Греческие символы |
RUSSIAN_CHARSET | 204 | Символы кириллицы |
EASTEUROPE_CHARSET | 238 | Включает диалектические знаки (знаки, добавляемые к буквам и характеризующие их произношение) для восточно-европейских языков |
Класс TPEN. Карандаш (перо) используется как инструмент для рисования точек, линий, контуров геометрических фигур. Основные свойства объекта Canvas.TPen:
- Color (тип Tcolor) — определяет тип линии;
- Width (тип Integer) — задаёт толщину линии в пикселях;
- Style — даёт возможность выбрать вид линии. Это свойство может принимать значение, указанное в таблице 10.3.
- Mode — определяет, каким образом взаимодействуют цвета пера и полотна. Выбор значения этого свойства позволяет получать различные эффекты. Возможные значения Mode приведены в табл. 10.4. По умолчанию вся линия вычерчивается цветом, определяемым значением Pen.Color, но можно определять инверсный цвет линии по отношению к цвету фона. В этом случае независимо от цвета фона, даже если цвет линии и фона одинаков, линия будет видна.
Режим | Операция | Цвет пикселя |
---|---|---|
pmBlack | Black | Всегда чёрный |
pmWhite | White | Всегда белый |
pmNop | — | Неизменный |
pmNot | Not Screen | Инверсный цвет по отношению к цвету фона |
pmCopy | Pen | Цвет, указанный в свойствах Color пера Pen (это значение принято по умолчанию) |
pmNotCopy | Not Pen | Инверсия цвета пера |
pmMergePenNot | Pen or Not Pen | Дизъюнкция цвета пера и инверсного цвета фона |
pmMaskPenNot | Pen and Not Screen | Конъюнкция цвета пера и инверсного цвета фона |
pmMergeNotPen | Not Pen or Screen | Дизъюнкция цвета фона и инверсного цвета пера |
PmMaskNotPen | Not Pen and Screen | Конъюнкция цвета фона и инверсного цвета пера |
pmMerge | Pen or Screen | Дизъюнкция цвета пера и цвета фона |
pmNotMerge | Not (Pen or Screen) | Инверсия режима pmMerge |
pmMask | Pen and Screen | Конъюнкция цвета пера и цвета фона |
pmNotMask | Not (Pen and Screen) | Инверсия режима pmMask |
pmXor | Pen xor Screen | Операция xor над цветом пера и цветом фона |
pmNotXor | Not (Pen xor Screen) | Инверсия режима pmXor |
Класс TBRUSH. Кисть (Canvas.Brush) используется методами, обеспечивающими вычерчивание замкнутых фигур для заливки. Кисть обладает двумя основными свойствами:
- Color (тип Tcolor) — цвет закрашивания замкнутой области;
- Style (тип TBrushStyle) — определяет стиль заполнения области (bsSolid — сплошное заполнение, bsClear — прозрачное, bsHorizontal — горизонтальные линии, bsVertical — вертикальные линии, bsFDiagonal, bsBDiagonal — диагональные линии, bsCross — решётка, bsDiagCross — диагональная решетка).
Класс TCANVAS. Этот класс является основным инструментом для рисования графики. Рассмотрим его наиболее часто используемые методы.
procedure MoveTo(X, Y : integer );
Метод MoveTo изменяет текущую позицию пера на позицию, заданную точкой (X,Y). Текущая позиция хранится в переменной PenPos типа Tpoint. Определение типа TPoint следующее:
type TPoint =record X : longint; Y: longint; end;
Текущую позицию пера можно считывать с помощью свойства PenPos следующим образом:
X:=PenPos.X; Y:=PenPos.Y;
procedure LineTo (X, Y : integer);
Метод LineTo соединяет прямой линией текущую позицию пера и точку с координатами (X,Y). При этом текущая позиция пера перемещается в точку с координатами (X,Y).
Рассмотрим работу процедуры на примере. Расположим на форме кнопку и рассмотрим процедуру обработки события TForm1.Button1Click, которая рисует прямые линии:
procedure TfForm1. Button1Click ( Sender : TObject ) begin Form1. Canvas. LineTo ( 30, 50 ); end;
В результате щелчка по кнопке на форме будет нарисована прямая линия, соединяющая точку с координатами (0,0) и точку с координатами (30,50). При повторном щелчке по кнопке процедура продолжит рисовать эту же линию.
Теперь перепишем процедуру обработки события следующим образом:
procedure TForm1. Button1Click ( Sender : TObject ) begin Form1. Canvas. LineTo ( Canvas. PenPos. x+30, Canvas. PenPos. y +50); end;
При первом щелчке по кнопке на экране прорисуется аналогичная линия. Но при повторном щелчке процедура рисует линию, которая соединяет текущую точку с точкой, получившейся из текущей добавлением к координате X числа 30, а к координате Y — числа 50. Т. е. при повторном щелчке по кнопке процедура соединяет прямой линией точки (30,50) и (60,100). При третьем щелчке по кнопке будут соединяться прямой линией точки (60,100) и (90,150) и т. д.
procedure PolyLine ( const Points array of TPoint );
Метод PolyLine рисует ломаную линию, координаты вершин которой определяются массивом Points.
Рассмотрим работу процедуры на примере. Расположим на форме кнопки Рисовать и Выход и запишем следующие операторы процедур обработки события:
procedure TForm1. Button1Click ( Sender : TObject ); var temp : array [ 1.. 2 5 ] of TPoint; i : byte; j : integer; begin j : = 1; for i :=1 to 25 do begin //вычисление координат вершин ломаной линии temp [ i ]. x:=25+( i _ 1) _ 10; temp [ i ]. y:=150 _ j _ ( i _ 1) _ 5; j :=- j; end; Form1. Canvas. Polyline ( temp ); end; procedure TForm1. Button2Click ( Sender : TObject ); begin Form1. Close; end;
После запуска программы и щелчка по кнопке Рисовать окно формы будет выглядеть, как на рисунке 10.1.
procedure Ellipse (X1, Y1, X2, Y2 : integer );
Метод Ellipse вычерчивает на холсте эллипс или окружность. X1, Y1, X2, Y2 — это координаты прямоугольника, внутри которого вычерчивается эллипс. Если прямоугольник является квадратом, то вычерчивается окружность.
procedure Arc (X1, Y1, X2, Y2, X3, Y3, X4, Y4 : integer );
Метод Arc вычерчивает дугу эллипса. X1, Y1, X2, Y2 — это координаты, определяющие эллипс, частью которого является дуга; X3, Y3 — координаты, определяющие начальную точку дуги; X4, Y4 — координаты, определяющие конечную точку дуги. Дуга рисуется против часовой стрелки.
procedure Rectangle (X1, Y1, X2, Y2 : integer );
Метод Rectangle рисует прямоугольник. X1, Y1, X2, Y2 — координаты верхнего левого и нижнего правого углов прямоугольника.
procedure RoundRect (X1, Y1, X2, Y2, X3, Y3 : integer );
Это метод вычерчивания прямоугольника со скруглёнными углами. X1, Y1, X2, Y2 — координаты верхнего левого и нижнего правого углов прямоугольника, а X3, Y3 — размер эллипса, одна четверть которого используется для вычерчивания скругленного угла.
procedure PolyGon ( const Points array of TPoint );
Метод PolyGon рисует замкнутую фигуру (многоугольник) по множеству угловых точек, заданному массивом Points. При этом первая точка соединяется прямой линией с последней. Этим метод PolyGon отличается от метода Poliline, который не замыкает конечные точки. Рисование осуществляется текущим пером Pen, а внутренняя область фигуры закрашивается текущей кистью Brush.
procedure Pie (X1, Y1, X2, Y2, X3, Y3, X4, Y4 : integer );
Метод Pie рисует замкнутую фигуру — сектор окружности или эллипса — с помощью текущих параметров пера Pen, внутренняя область закрашивается текущей кистью Brush. Точки (X1,Y1) и (X2,Y2) задают прямоугольник, описывающий эллипс. Начальная точка дуги определяется пересечением эллипса с прямой, проходящей через его его центр и точку (X3,Y3). Конечная точка дуги определяется пересечением эллипса с прямой, проходящей через его центр и точку (X4,Y4). Дуга рисуется против часовой стрелки от начальной до конечной точки. Рисуются прямые, ограничивающие сегмент и проходящие через центр эллипса и точки (X3,Y3) и (X4,Y4).
Создадим форму, установим ей размеры Heigth — 500, Weight — 500. Внизу разместим кнопку, зададим ей свойство Caption — "Рисовать". При запуске программы и щелчке по этой кнопке на форме прорисуются различные фигуры (см. рис. 10.2). Ниже приведён листинг программы, демонстрирующий работу перечисленных методов. Результат работы программы приведен на рис. 10.2.
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class (TForm) Button1 : TButton; procedure Button1Click ( Sender : TObject ); private { private declarations } public { public declarations } end; var Form1 : TForm1; implementation { TForm1 } procedure TForm1. Button1Click ( Sender : TObject ); var t : array [ 1.. 5 ] of TPoint; begin //рисование линии Form1. Canvas. LineTo ( 500, 500 ); //изменяем цвет и толщину линии Form1. Canvas. Pen. Color := clMaroon; Form1. Canvas. Pen. Width:= 5; //рисование прямоугольника Form1. Canvas. R e c tan gle ( 50, 50, 200, 200 ); Form1. Canvas. Pen. Color := clolive; //рисование эллипса Form1. Canvas. Ellipse ( 50, 50, 100, 200 ); //рисование прямоугольника со скруглёнными углами Form1. Canvas. RoundRect ( 250, 250, 400, 400, 30, 30 ); //рисование сектора окружности Form1. Canvas. Pie ( 300, 300, 400, 400, 350, 350, 500, 500 ); //формирование массива координат вершин пятиугольника t [ 1 ]. x :=250; t [ 1 ]. y := 10; t [ 2 ]. x :=350; t [ 2 ]. y := 15; t [ 3 ]. x :=400; t [ 3 ]. y := 50; t [ 4 ]. x :=300; t [ 4 ]. y :=150; t [ 5 ]. x :=250; t [ 5 ]. y :=100; Form1. Canvas. Polygon ( t ); Form1. Canvas. TextOut ( 10, 10, ’это вывели текст ’ ); end; initialization {$I unit1.lrs} end.
procedure TextOut (X, Y : integer; const Text : String );
Эта функция пишет строку текста Text, начиная с позиции с координатами (X,Y). Текущая позиция PenPos пера Pen перемещается в конец выведенного текста. Надпись выводится в соответствии с текущими установками шрифта Font, фон надписи определяется установками текущей кисти. Для выравнивания позиции текста на канве можно использовать методы, позволяющие определить высоту и длину текста в пикселях — TextExtent, TextHeight и TextWidth. Рассмотрим эти функции.
function TextExtent ( const Text : String ) : Tsize;
Эта функция возвращает структуру типа Tsize, содержащую длину и высоту в пикселях текста Text, который предполагается написать на канве текущим шрифтом.
type Tsize = record cx : longint; cx : longint; end;
function TextHeight ( const Text : String ) : integer;
Функция возвращает высоту в пикселях текста Text, который предполагается написать на канве текущим шрифтом.
function TextWidth ( const Text : String ) : integer;
Функция возвращает длину в пикселях текста Text, который предполагается написать на канве текущим шрифтом. Это позволяет перед выводом текста на канву определить размер надписи и расположить её и другие элементы изображения наилучшим образом.
Если цвет кисти в момент вывода текста отличается от того, которым закрашена канва, то текст будет выведен в цветной прямоугольной рамке, но её размеры будут точно равны размерам надписи.
Мы рассмотрели основные функции рисования. Теперь можно перейти непосредственно к рисованию. Но перед этим следует заметить, что если вы свернёте окно с графикой, а затем его восстановите, то картинка на форме исчезнет. Изменение размеров окна также может испортить графическое изображение в нём. Для решения этой проблемы существуют процедуры обработки событий Объект.FormPaint и Объект.FormResize. Процедура Объект.FormPaint выполняется после появления формы на экране, а процедура Объект.FormResize — после изменения размера формы. Следовательно, все операторы рисования нужно помещать внутрь Объект.FormPaint и дублировать в процедуре Объект.FormResize.