Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика_лекции.doc
Скачиваний:
45
Добавлен:
25.11.2018
Размер:
5.13 Mб
Скачать

16.6. Обновление изображения

Помимо объекта Image, рисовать можно непосредственно на форме или панели. Например, проведем белые диагональные полосы на форме, превратив ее в подобие Андреевского флага. Для этого напишем следующий обработчик нажатия на кнопку:

procedure TForm1.Button1Click(Sender: TObject);

begin

with Self.Canvas do

begin

Pen.Color:=clWhite;

Pen.Width:=20;

MoveTo(0,0);

LineTo(Self.ClientWidth,Self.ClientHeight);

MoveTo(Self.ClientWidth,0);

LineTo(0,Self.ClientHeight)

end

end;

Данный фрагмент проводит две белые полосы шириной в 20 пикселов по диагонали формы. Точка (0,0) формы находится в ее левом верхнем углу. Обратите внимание, что для определения размеров формы используются свойства формы ClientWidth и ClientHeight, а не просто Width и Height. Дело в том, что свойства Width и Height содержат полный размер формы, включая полоску заголовка, а ClientWidth и ClientHeight – лишь размеры так называемой клиентской части формы, на которой можно размещать другие объекты.

Если запустить нашу программу и щелкнуть по кнопке, полосы действительно отрисуются (Рис. 16.13, а). Но... Попробуем перетащить окно программы так, чтобы оно частично оказалось за пределами экрана, а потом вытащим его обратно. О, ужас! На части окна, побывавшей за границей экрана, линии стерлись! (Рис. 16.13, б). Причем при использовании объекта Image подобный эффект не наблюдается.

а)

б)

Рис. 16.13. Потеря части изображения.

Как бороться с таким безобразием? Увы, единственный способ – перерисовывать картинку всякий раз, когда часть изображения затирается. Для этого вынесем все команды рисования в отдельную процедуру Draw:

procedure Draw;

begin

with Form1.Canvas do

begin

Pen.Color:=clWhite;

Pen.Width:=20;

MoveTo(0,0);

LineTo(Form1.ClientWidth,Form1.ClientHeight);

MoveTo(Form1.ClientWidth,0);

LineTo(0,Form1.ClientHeight)

end

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

Draw

end;

procedure TForm1.FormPaint(Sender: TObject);

begin

Draw

end;

В данном фрагменте добавлен обработчик события формы OnPaint. Это событие происходит всякий раз, когда форму надо перерисовывать. Соответственно в такие моменты и вызывается процедура Draw. Теперь с исчезновениями частей изображения покончено.

Лекция 17. Построение динамических изображений

Анимация в Delphi создается двумя основными способами. Давайте изобразим звездное небо, по которому летит летающая тарелка. При этом нужно обеспечить автоматическое восстановление фона под движущейся картинкой.

17.1. Анимация на основе операции xor

Первый способ основан на хитром свойстве логической операции XOR. Поместим на форму кнопку и объект Image1 с шириной, в два раза превышающей высоту. Сначала нарисуем небо – это мы уже умеем. Теперь надо нарисовать летающую тарелку. Их толком никто не видел, поэтому особой точности в деталях не требуется. Давайте вынесем команды рисования тарелки в отдельную процедуру, это заметно облегчит жизнь в дальнейшем.

PROCEDURE Ufo(x,y:INTEGER);

BEGIN

WITH Form1.Image1.Canvas DO

BEGIN

Pen.Color:=clBlue;

Pen.Width:=3;

Ellipse(x,y,x+20,y+10)

END

END;

Осталось организовать движение тарелки по экрану. Делается это в обработчике нажатия на кнопку примерно так:

Pen.Mode:=pmNOTXOR;

FOR i:=0 TO Image1.Width DO

BEGIN

Ufo(i, i DIV 2);

Application.ProcessMessages;

Sleep(10);

Ufo(i, i DIV 2)

END

END;

Самая важная строчка в этом фрагменте - Pen.Mode:=pmNOTXOR. Она устанавливает режим вывода графики "исключающее ИЛИ". При таком режиме вывод одной и той же картинки дважды в одно и то же место изображения приводит к автоматическому восстановлению фона под картинкой. Такой эффект основан на свойстве логической операции "исключающее ИЛИ": если a XOR b=c, то с XOR b=a. В цикле картинка выводится первый раз (вызов процедуры Ufo), затем выполняется команда Application.ProcessMessages, обеспечивающая немедленное отображение НЛО на экране и делается задержка на 10мс, чтобы мы успели увидеть, что получилось. Далее НЛО выводится в то же самое место еще раз, при этом изображение тарелки пропадет, а под ней автоматически восстановится фон. Координаты тарелки меняются и по Х, и по Y, поэтому она поедет по экрану вправо вниз.

Запускаем… Красиво? Нет! Экран безобразно мерцает. Что делать? Спокойно, это просто еще один фокус Delphi. Чтобы динамическое изображение на форме не мерцало, в начало процедуры вывода анимации надо добавить строчку

Form1.DoubleBuffered:=TRUE;

Окончательный вариант обработчика имеет вид:

procedure TForm1.Button1Click(Sender: TObject);

var i:word;

begin

DoubleBuffered:=true;

with Image1.Canvas do

begin

Brush.Color:=clBlack;

FillRect(Image1.ClientRect);

for i:=1 to 500 do

Pixels[Random(Image1.Width),Random(Image1.Height)]

:=clWhite;

Pen.Mode:=pmNOTXOR;

FOR i:=0 TO Image1.Width DO

BEGIN

Ufo(i, i DIV 2);

Application.ProcessMessages;

Sleep(10);

Ufo(i, i DIV 2)

END

END

end;

Вот теперь наш мультик будет смотреться вполне неплохо, если бы не одна неприятность. Мы заказывали тарелку синего цвета (строчка Pen.Color:=clBlue), а получили желтого. Причина – в операции "исключающее ИЛИ". Она неизбежно искажает цвета выводимых на экран точек. Поэтому создать нормальную многоцветную анимацию таким способом затруднительно.