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

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

TPen – перо, определяет вид линий и обладает следующими свойствами: Color – цвет линии, Mode – режим вывода (простая линия, с инвертированием..., см. приложение 7), Style – стиль вывода линий контура (сплошная – psSolid, без контура – psClear, пунктир для ширины линий 1 пиксель – psDash,…), Width – ширина линии в пикселях.

П р и м е р 3.37

На рис. 3.12 приведен интерфейс приложения до и после нажатия на клавишу Start. Форма содержит объекты Shape1, Shape2 и Image1, причем, начальное свойство объекта Shape2 (круг) Visible=False, т.е. вначале он невидим.

Рис. 3.12 Демонстрация объектов Shape и Image

{ Код обработчика клавиши Start: }

procedure TForm1.Button1Click(Sender: TObject);

begin

 

Button1.Visible:=False;

{ спрятать кнопку "Start" }

Image1.Picture.LoadFromFile('Fig2.bmp');

{ - загрузить рисунок из файла Fig2.bmp в окно Image1 }

Shape1.Brush.Color:=clRed;

{ красное заполнение для Shape1 }

Shape1.Pen.Color:=clWhite; { белый контур для Shape1 }

Shape2.Visible:=True;

{ показать фигуру Shape2 }

End;

 

100

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

3.10.2 Компонент TCanvas

TCanvas (канва, холст) – это невизуальный компонент, входящий как свойство Canvas в многие другие визуальные компоненты, использующие холст для рисования. Доступ к нему возможен только посредством написания кодов программы. Канва предоставляет путь для рисования на объектах

TComboBox, TForm, TImage, TListBox, TPaintBox, TStringGrid и др.,

которые обладают свойством Canvas. TCanvas объединяет в себе поле для рисования, карандаш (Pen), кисть (Brush) и шрифт (Font). Он содержит множество графических методов: Draw, TextOut, Arc, Rectangle и др. Используя канву можно воспроизводить на форме любые графические объекты: картинки, многоугольники, текст и т.п., без использования компонент TImage и TShape (т.е. без использования дополнительных ресурсов).

Рисование на канве организуется с учетом относительных координат её поля, а не координат всей формы. Это означает, что левый верхний угол канвы всегда имеет координаты (0,0), ось абсцисс возрастает слева направо, а ординат – сверху вниз. Единицы измерения осей – это пиксели экрана. Очевидно, что они могут иметь только целые значения. Координата правого нижнего угла канвы – это её свойства Width и Height.

Прямоугольную область рисования можно задать с помощью стандартной функции

Rect(ALeft, ATop, ARight, ABottom: Integer): TRect;

где параметры функции – это координаты левого верхнего угла (ALeft,ATop) прямоугольника и его правого нижнего – (ARight,ABottom). Если прямоугольник совпадает со всей канвой, то к нему можно обращаться через свойство канвы ClientRect, которое совпадает с Rect(0,0,Width,Height). Кстати многие компоненты Delphi обладают этим свойством. Функция Rect имеет тип TRect, который является записью

TRect=Record Left, Top, Right, Bottom: Integer; end;

Таким образом, если мы хотим рисовать в прямоугольнике (5,5,100,100), обозначим его через R, то мы должны описать var R: TRect; а в теле программы сделать присваивание R:=Rect(5,5,100,100); При этом, например, левая граница прямоугольника относительно канвы будет иметь идентификатор R.Left равный 5 пикселей.

Теперь рассмотрим подробнее свойства и методы канвы.

Свойства канвы:

Brush, Pen были рассмотрены ранее.

CopyMode – определяет как будет происходить копирование на данную канву изображения из другого места методом CopyRect: один к

101

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

одному, с инверсией изображения и др. (см. приложение 7).

Font – шрифт, которым будет рисоваться текст. Данное свойство также является компонентом TFont со своими свойствами: Charset конкретизирует набор символов для выбранного имени шрифта; Color – цвет шрифта; Height – высота шрифта в пикселях; Name – имя шрифта; Size

– высота шрифта в пунктах; Style – множество стилей написания шрифта. Приведем пример:

With Canvas.Font Do begin

Color:=clRed;

Name:=’Times New Roman’;

Size:=20;

Style:=[fsBold,fsItalic]; {полужирный и наклонный}

end;

Описание значений всех свойств шрифта можно найти через подсказку F1 для компонента TFont или в свойстве Font инспектора объектов.

PenPos – координаты текущей позиции X,Y. Это свойство является записью типа TPoint=Record X: Integer; Y: Integer; end;

Оно очень удобно, например, при позиционировании повторного вывода текста в конец предыдущего с изменением шрифта:

With Canvas Do begin

Font.Name:='Arial'; TextOut(X,Y,'График функции '); Font.Name:='Arial Bold'; TextOut(PenPos.X,PenPos.Y,'Sin(x)');

end;

Pixels[X,Y] – цвет пикселя в точке X,Y. Лучше этим свойством не пользоваться из-за низкой скорости его работы.

Методы канвы:

Методы для рисования на канве:

Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4) – рисует против часовой стрелки дугу эллипса, ограниченного прямоугольником с координатами X1, Y1, X2, Y2. Начало дуги – это пересечение с лучом, выходящим из центра эллипса и проходящим через точку X3, Y3. Конец дуги – это пересечение с лучом, выходящим из центра эллипса и проходящим через точку X4, Y4.

Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4) – рисует заполненный эллипс без части, которую «отрезает» хорда, соединяющая концы дуги эллипса;

CopyRect(<цель>: TRect; Canvas: TCanvas; <источник>: TRect) – копиру-

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

PaintBox2.Canvas.CopyMode:=cmSrcCopy;

102

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

PaintBox2.Canvas.CopyRect(Rect(30,70,120, 150),

PaintBox1.Canvas,PaintBox1.ClientRect);

Ellipse(X1, Y1, X2, Y2) – рисует эллипс, ограниченный прямоугольником с координатами X1, Y1, X2, Y2.

FloodFill(X, Y, <цвет>, <стиль заполнения>) – заполняет область, включающую точку X,Y, цветом заполнения, установленном в Brush. Если стиль заполнения – fsSurface, то заполнение распространяется только на область указанного цвета, если – fsBorder, то – на область, ограниченную контуром указанного цвета;

LineTo(X, Y) – рисует прямую линию в точку X, Y из текущей позиции, установленной методом MoveTo. Текущая позиция переносится в конечную точку;

MoveTo(X, Y) – устанавливает текущую позицию в точку X, Y;

Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4) – рисует заполненный сектор эллипса. Параметры аналогичны методу Arc;

Polygon(Points: array of TPoint) – рисует заполненный многогранник по массиву точек Points. Первая и последняя точки соединяются автоматически. Элементы массива Points – это записи типа TPoint (см. свойство

PenPos)

PolyLine(Points: array of TPoint) – рисует ломаную линию по массиву точек Points. В отличие от LineTo текущая позиция не меняется;

Rectangle(X1, Y1, X2, Y2) – рисует заполненный прямоугольник. Для того чтобы заполнить прямоугольную область без контура используйте метод FillRect(Rect(X1, Y1, X2, Y2). Чтобы нарисовать прямоугольник без заполнения используйте метод FrameRect(Rect(X1, Y1, X2, Y2) или Polygon.

RoundRect(X1, Y1, X2, Y2) – рисует заполненный прямоугольник со скругленными углами;

При прорисовке линий (контуров) в этих методах используются карандаш Pen канвы, а для заполнения внутренних областей – кисть Brus.

Очистка канвы – это заполнение всей её области каким-либо однородным цветом, обычно – белым. Такую «очистку» можно и удобно реализовывать с помощью процедуры, приведенной в следующем примере.

П р и м е р 3.38

Процедура очистка канвы:

procedure ClearCanvas(ACanvas: TCanvas; AR: TRect); begin

With ACanvas Do begin

Brush.Style:=bsSolid;

Brush.Color:=clWhite;

103

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

FillRect(AR); end;

end;

Обращение к такой процедуре может иметь вид:

//Очистка всей канвы объекта PaintBox1:

ClearCanvas(PaintBox1.Canvas,PaintBox1.ClientRect);

//Очистка верхней половины канвы объекта Image1:

ClearCanvas(Image1.Canvas,

Rect(0,0,Image1.Width,Image1.Height div 2));

Методы для вывода картинок на канву:

Draw(X, Y, <идентификатор объекта Bitmap>) – рисует прямоугольную картинку с координатой левого верхнего угла X,Y. Картинка должна находится в объекте типа TBitmap.

StretchDraw(Rect(X1,Y1,X2,Y2), <идентификатор объекта Bitmap >) –

отличается от Draw тем, что растягивает или сжимает картинку так, чтобы она заполнила всю канву. Смотрите пример 3.39.

Методы для вывода текста на канву:

TextOut(X,Y, текст) – рисует строку текста, начиная с позиции X,Y (левый верхний угол строки) и помещает текущую позицию в конец текста (правый верхний угол строки). Посмотрите пример, для описанного выше свойства PenPos. При выводе текста используется текущий шрифт Font. Длину и высоту строки текста можно узнать с помощью функций

TextWidth(строка): Integer и TextHeight(строка): Integer.

TextRect(Rect(X1,Y1,X2,Y2), X,Y, текст) – рисует строку текста,

начиная с позиции X,Y внутри указанного прямоугольника. Не помещающийся текст отбрасывается.

П р и м е р 3.39

На рис. 3.13 приведен интерфейс приложения рисующего голову кота после нажатия на клавишу Start. Непосредственно рисунок выполнен справа на канве объекта PaintBox1.

Ниже приведен обработчик события onPaint главной формы – процедура FormPaint, которая создает на форме приложения фон в виде облаков из файла Clouds.bmp и выводит заголовок рисунка. Поскольку кот нарисован в объекте типа TPaintBox, то для его прорисовки, при каждом выходе окна на передний план, в конце обработчика добавлен оператор If, вызывающий процедуру рисования кота, если клавиша Start уже была нажата. Эта процедура является обработчиком кнопки Start, которой дан идентификатор btnStart.

104

Рис. 3.13 Демонстрация свойств и методов канвы для TForm и TPaintBox

procedure TForm1.FormPaint(Sender: TObject); var Clouds: TBitmap;

begin try

Clouds:=TBitmap.Create; {- создать Bitmap с именем Clouds} Clouds.LoadFromFile('C:\Windows\Clouds.bmp');

{- загрузить Clouds из файла C:\Windows\Clouds.bmp}

//Нарисовать Clouds на всей канве формы:

Form1.Canvas.StretchDraw(ClientRect,Clouds);

finally

Clouds.Free;{освободить память, занимаемую объектом Clouds} end;

// Написать заголовок «Рисунок кота»:

With Canvas.Font Do begin

Name:='Arial Bold'; Size:=16; Color:=clBlue;

end;

Canvas.Brush.Style:=bsClear; {прозрачный фон для текста} Canvas.TextOut(65,10,'Рисунок кота');

// Если кнопка Start была нажата – сделать прорисовку:

If not btnStart.Enabled Then btnStartClick(Sender); end;

Теперь напишем процедуру, непосредственно рисующую кота на канве PaintBox1 после щелчка на кнопке Start. В процедуре специально использо-

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

вано свойство канвы Pixels для демонстрации его низкоскоростных возможностей, если, конечно, Вы повторите на практике этот пример.

procedure TForm1.btnStartClick(Sender: TObject);

Var i,j : Integer;

 

begin

 

btnStart.Enabled:=False;

{отключить кнопку Start}

For i:=1 to Width Do For j:=1 to Height Do PaintBox1.Canvas.Pixels[i,j]:=i*clLime; {разноцветный

прямоугольник на всей канве PaintBox1}

// Рисование кота:

With PaintBox1.Canvas Do begin Font.Name:='Times New Roman'; Font.Size:=12; Font.Color:=clWhite; Brush.Style:=bsClear;

TextOut(160,60,'Мяу !');

{текст «Мяу!»}

// голова кота:

Pen.Color:=clBlue; Brush.Color:=clYellow; Pie(70,25,130,100,20,20,160,20);

// глаза кота:

Pen.Color:=clBlack; Brush.Color:=clBlack; Ellipse(80,70,90,80); Ellipse(110,70,120,80);

// усы кота:

MoveTo(95,90); LineTo(60,80);

MoveTo(105,90); LineTo(140,80); end;

end;

Задание 11.

Построение графика функции

Цель задания

1.Знакомство с графическими компонентами Delphi.

2.Приобретение навыков рисования графиков.

Постановка задачи

Построить график функции u(t) , полученной в лабораторной работе 9 при

решении задачи Коши. График должен быть оформлен в соответствии с требованиями стандартов. Интерфейс программы может иметь вид, показанный на рис. 3.14.

106

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

Рис. 3.14 Пример интерфейса приложения с графиком решения u(t) задачи Коши из лабораторной работы 9

Рекомендации:

Для построения графика используйте метод PolyLine, соединяющий отрезками дискретные значения функции u(t) , рассчитанные в лабораторной работе 9. Для этого, во-первых, оформите решение задачи Коши – вычисление функции u(t) – в виде Object Pascal функции, например, fun(t). Во-вторых, представьте результаты расчетов функции как массив элементов TPoint точек канвы, где для каждого элемента массива поле X будет масштабированным временем ti, а Y – масштабированным значением функции u(ti). Описание такого типа-массива (динамического массива) должно иметь вид:

var u: Array of TPoint;

Элементы этого массива целесообразно заполнять по следующему алгоритму:

For i:=0 To High(u) Do With u[i] Do begin

x:=Trunc(i*dt*kx)+x0;

y:=Trunc(fun(i*dt)*ky)+y0;

end;

Здесь коэффициенты kx, ky – это масштабные множители, переводящие математические значения t и u в значения координат канвы, на которой

107

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

будет рисоваться график, (x0,y0) – координаты начала рисования графика, dt – шаг по времени t . Выражения для kx, ky найдите самостоятельно, но не путем вычислительного эксперимента. Они должны завесить от количества узлов n сетки ω t , размеров канвы и максимально возможного

значения функции u(t) на интервале (0, T ). Поскольку значения координат

рисования могут быть только целыми, то при всех их вычислениях используйте операцию целочисленного деления div и преобразования к целому типу стандартными функциями Trunc или Round.

Для красивого расположения рисунка, оставляйте пустые поля вокруг него. Это легко сделать, если компонент рисования поместить на объекте TShape немного большего размера с цветом фона как у графика. Оси координат целесообразно рисовать после задания начальной точки (x0,y0). Координату x0 не следует устанавливать нулевой, поскольку слева от неё придется делать надписи для оси ординат. Теперь, например, ось абсцисс и надписи на ней, соответствующие рисунку 3.12, можно задать как

With PaintBox1.Canvas Do begin

MoveTo(x0,y0); LineTo(PaintBox1.Width,y0); // ось X Font.Name:='Symbol'; Font.Size:=10; Brush.Style:=bsClear;

TextOut(x0 div 2,y0,'0'); TextOut((PaintBox1.Width-x0) div 2 + x0 –

TextWidth('p') div 2, y0,'p'); TextOut(PaintBox1.Width-TextWidth('2p'),y0,'2p');

end;

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

Очищайте область рисования графика процедурой, описанной в примере 3.38.

Нарисовать график можно и не так элегантно, как это делает метод PolyLine с массивом точек-записей, содержащим сразу обе координаты X и Y всей кривой. Данный метод требует выделять память, по существу, для двухмерного массива 2*(n+1) элементов. Если это неприемлемо, например, при очень больших n и, к тому же, если сетка ω t имеет равномерный шаг

t , то можно обойтись без массива точек-записей. При этом, после каждого расчета функции fun(t) в точке i*dt, необходимо новое значение функции соединить отрезком прямой по методу LineTo с её старым значением, которое хранится в текущей позиции канвы. Для

108

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

рисования графика таким способом необходимо установить начальную текущую позицию в точку (x0,y0) методом MoveTo.

Интерфейс приложения можно дополнить строкой состояния –

TStatusBar из закладки Win32 палитры компонент. Этот объект автоматически размещается внизу окна формы. Его основное свойство – SimpleText, которому и присваевается желаемая строка комментария.

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

1.Чем различаются компоненты TImage, TPaintBox, TBitmap?

2.Что такое Canvas и как с ней работать?

3.Как написать текст на каком-либо графическом объекте?

4.Какими способами можно построить кривую по заданным точкам?

5.Какой вид будет иметь кривая y = 0.4sin x , если при её рисовании не масштабировать функцию y ?

6.Когда возникает событие OnPaint?

7.Зачем нужен метод Repaint?

109