понедельник, 28 июля 2008 г.

Рисование на форме или на компоненте PaintBox.

Большое спасибо Александру, за идею примера, который мы рассмотрим в этом уроке. Извиняюсь за то, что перевел тему с генератора на построитель функции синуса и косинуса.
У формы и у компонента PaintBox (страница System палитры компонентов) есть свойство Canvas. Это свойство представляет собой растровое изображение, на котором можно рисовать или в которое можно загрузить рисунок. Я не буду рассказывать подробно об особенностях рисования, тем более, что я в этом не силен, но основные сведения дам.
Свойство Canvas доступно только во время работы приложения и с помощью его можно:
* Canvas.Brush - свойство фона. У него можно установить свойство Canvas.Brush.Color в необходимый цвет и с помощью следующей за ней командой Canvas.FillRect(ClientRect) можно очистить всю рабочую область компонента под заданный цвет. С помощью свойтва Canvas.Brush можно в качестве фона установить рисунок. Для этого есть свойство Canvas.Brush.Bitmap, которому нужно присваивать переменную с растровым рисунком.
* Canvas.MoveTo(x,y) - устанавливает перо в заданную точку, где x и y - координаты точки, относительно компонента. Начало координат, точка [0,0] находится в верхнем левом углу. После этой команды перо установлено, но точка не нарисована. Чтобы провести линию от текущего положения пера до заданного Canvas.LineTo(x,y). Поставить точку определенного цвета на холсте Canvas.Pixels[x,y]:=ЦВЕТ_ТОЧКИ.
* Через Canvas можно писать текст, рисовать дуги, сектор круга, овал, прямоугольник, ломаную линию, кривую.
* Свойства пера содержатся в Canvas.Pen. Здесь можно задать толщину пера Canvas.Pen.Width:=ТОЛЩИНА_В_ТОЧКАХ. Задать цвет Canvas.Pen.Color:=ЦВЕТ.

Рассмотрим пример генератора колебаний/ Генератор сам по себе есть только на экране. Колебания, которые он создает, рассчитываются по формуле.
Следовательно, он вам может оказаться полезным. Можно изменить рассчетную функцию и вы получите для этой функции график.

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

1. Программа имеет только одно окно Form1, у которого сразу переименовываем заголовок на подходящее название.
2. Устанавливаем свойство Form1.Position в poDesktopCenter, чтобы окно при каждом запуске и при любом экранном разрешении всегда было ровно посередине экрана.
3. Устанавливаем свойство Form1.BorderStyle в bsSingle, для неизменяемого размера окна. Оставляем во вложенных свойствах BorderIcons только biSystemMenu в true, остальные в false. Это для того, чтобы окно нельзя было свернуть в значек, развернуть во весь экран и окно имело иконку в заголовке.
4. Устанавливаем в форму компонент PaintBox, два компонента RadioButton, CheckBox, три кнопки Button и TrackBar, расположенный на странице Win32.
5. RadioButton1.Caption переименовываем в "Sin". Этот флаг будет признаком рисования синусоиды. RadioButton2.Caption переименовываем в "Cos" - косинусоида. Начальное значение флага Checked для RadioButton1 в true.
6. CheckBox1.Caption переименовываем в "Все". Если флаг установлен, то будет рисоваться два графика.
7. Названия кнопок Button1 - "Старт", Button2 - "Стоп (пауза)" и Button3 - "Выход". Названия на кнопках меняются через свойство Caption. Теперь назначение этих кнопок понятно.
8. Компонент TrackBar1 свойство минимального значения Min устанавливаем в 1, максимальное значение Max - 50.
9. PaintBox1, на котором будет непосредственно рисоваться график размеры высоты Height=140, ширина Width=500.

Привожу текст модуля для окна Form1.

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

Var stop:boolean; // признак рисования
x:Integer;
// координата оси X

Реакция на событие нажатия на кнопку Button1 (Начало рисования)

procedure TForm1.Button1Click(Sender: TObject);
Var y:Integer;
// ось Y
begin
if x=0 then
// если точка в начале координат, то:
begin
PaintBox1.Canvas.Brush.Color:=clWhite;
// цвет фона белый
PaintBox1.Canvas.FillRect(ClientRect);
// заливка всей рабочей области
end;
stop:=false;
// флаг старта процесса рисования
While not stop do
// бесконечный цикл, пока флаг остановки не поднят:
begin
if (RadioButton1.Checked)or(CheckBox1.Checked) then
// если установлен "Sin" или "Все", то:
begin
y:=Round(Sin(pi*x/100)*50)+70;
// вычисление положения синусоиды
PaintBox1.Canvas.Pixels[x,y]:=clBlack;
// нарисовать черную точку
end;
if (RadioButton2.Checked)or(CheckBox1.Checked) then
// если установлен "Cos" или "Все", то:
begin
y:=Round(Cos(pi*x/100)*50)+70;
// вычисление положения косинусоиды
PaintBox1.Canvas.Pixels[x,y]:=clBlack;
// нарисовать черную точку
end;
inc(x);
// увеличить значение X на едицину. Аналог X:=X+1
if x>500 then
// если X вышел за пределы PaintBox1, то:
begin
x:=0;
// установить X на начало координат
PaintBox1.Canvas.Brush.Color:=clWhite;
// Цвет фона белый
PaintBox1.Canvas.FillRect(ClientRect);
// Очистка рабочей области PaintBox1
end;

Sleep(TrackBar1.Position);
// Процедура "засыпает" на заданное время в миллисекундах
Application.ProcessMessages;
// Обработка всей очереди сообщений
end;
end;


Коротко расскажу работу этой процедуры.
Как только нажата кнопка "Старт" Компонент PaintBox1 очищается и начинается бесконечный цикл While, выйти из которого можно только, пока переменная Stop не примет значение true. Это можно сделать кнопкой Button2, соответствующая процедура которой обработается во время Application.ProcessMessages. С помощью бегунка TrackBar1 можно менять скорость рисования кривой. Этот параметр передается в команду Sleep.

Процедура нажатия на кнопку остановки Button2:

procedure TForm1.Button2Click(Sender: TObject);
begin
Stop:=true;
// установить флаг остановки процесса рисования
end;


Процедура создания окна Form1OnCreate:

procedure TForm1.FormCreate(Sender: TObject);
begin
x:=0;
// начальное значение X
end;


Если нажата кнопка "Выход", то реакция на это событие будет таким:

procedure TForm1.Button3Click(Sender: TObject);
begin
Close;
// закрыть окно
end;


И реакция перед закрытием окна OnClose. Без этой процедуры, если рисование включено, то окно не закроется.

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Stop:=true;
// остановить (если включен) цикл рисования
end;


После запуска программы, установки флажка "Все" и нажатии на кнопку "Старт" на экране отобразится этот график:


В принципе, с нашей программой можно отслеживать практически любые функции. Просто надо описать свою отслеживаемую функцию вместо моих строк Y:=Sin...
Если вы хотите убрать постоянную прорисовку графика функции, то следующий код в программе

if x>500 then // если X вышел за пределы PaintBox1, то:
begin
x:=0;
// установить X на начало координат
PaintBox1.Canvas.Brush.Color:=clWhite;
// Цвет фона белый
PaintBox1.Canvas.FillRect(ClientRect);
// Очистка рабочей области PaintBox1
end;

измените на:

if x>500 then // если X вышел за пределы PaintBox1, то:
begin
x:=0;
// установить X на начало координат
Stop:=true;
// остановка рисования
end;


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

Y:=140 - ФУНКЦИЯ;

Как видите, поле для экспериментов велико.

Комментариев нет: