Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
mage1.Width, Image1.Height DIV 2
Image1.Width DIV 2, Image1. Height
0, Image1.Height DIV 2
Image1.Width DIV 2, 0
Y
Х
начало
координат
Министерство образования и науки РФ
Федеральное бюджетное государственное
образовательное учреждение
высшего профессионального образования
«Тульский государственный университет»
Политехнический институт
Кафедра "Автоматизированные станочные системы"
Троицкий Д.И.
доцент, к.т.н.
МЕТОДИЧЕСКИЕ УКАЗАНИЯ
ПО ВЫПОЛНЕНИЮ ЛАБОРАТОРНОЙ РАБОТЫ №8
по дисциплине
ИНФОРМАТИКА
Направление подготовки:
230100 Информатика и вычислительная техника
Профиль подготовки:
Системы автоматизированного проектирования
Форма обучения очная, очно-заочная, заочная
Тула 2011 г.
Рассмотрено на заседании кафедры "Автоматизированные станочные системы"
протокол №1 от "31" августа 2011 г.
Зав. кафедрой________________А.Н. Иноземцев
СОДЕРЖАНИЕ
[1] 1. Графика в Delphi [2] 2. Простейшие построения [3] 3. Построение графиков функций [4] 4. Построение геометрических фигур [5] 5. Построение динамических изображений [6] 6. Анимация в Delphi [7] 7. Работа с таймером [8] 8. Использование таймеров в графике |
Хорошие снимки обычно делаются при закрытом объективе.
Из законов Мэрфи
Для вывода изображений на форме необходимо разместить один из графических компонентов. Графический компонент представляет собой окно со своей системой координат, в котором можно выполнять разнообразные построения. Проще всего использовать объект Image, находящийся на закладке Additional (). Поместите объект Image на форму (рис. 1).
Рис. 1 Графический компонент Image.
В Image можно загрузить статическую картинку из файла в формате bmp, gif, jpeg, ico, wmf, emf. Для этого щелкните мышью по кнопке с тремя точками рядом со свойством Picture и в открывшемся окне нажмите кнопку Load. Свойство Stretch указывает, будет ли загруженная из файла картинка вписана в прямоугольник на форме (пусть даже с искажениями) или, если она больше, будет отображаться только ее кусочек. Свойство AutoSize позволяет автоматически подстроить размер компонента (высоту и ширину) под размер загруженной картинки. Однако при этом компонент может даже вылезти за пределы формы.
Части, которые просто нельзя собрать неправильно,
все же будут собраны неправильно.
Из законов Мэрфи.
Построение изображений из программы основано на вызове методов объекта Canvas (по англ. "холст"). У объекта Image есть свойство Canvas, поэтому запись команд рисования выглядит примерно так:
Image1.Canvas.команда;
Принцип рисования в Delphi заключается в том, что картинка строится пером (pen), которое перемещается по холсту, проводя на нем линии. Кроме пера, у холста еще есть кисть (brush), которой можно закрашивать большие области. Наконец, имеются отдельные команды для построения отрезков, прямоугольников, эллипсов (окружность частный случай эллипса). Давайте нарисуем изображение, показанное на рис. 2.
Рис. 2 Пример изображения.
Прежде всего надо понимать, что размер нашего поля рисования в пикселах величина переменная. Пользователь может растянуть форму, поменять разрешение экрана и т.д. Поэтому ширину поля рисования нужно брать из свойства Image1.Width, а высоту из свойства Image1.Height.
Как и обычно, процедуру рисования будем писать так, чтобы она вызывалась при нажатии на кнопку. Для этого поместим на форму кнопку "Рисовать". Процедура рисования будет выглядеть следующим образом:
procedure TForm1.Button1Click(Sender: TObject);
begin
WITH Image1.Canvas DO
BEGIN
Brush.Color:=clWhite;
Pen.Color:=clBlack;
FillRect(Image1.ClientRect);
MoveTo(0,Image1.Height DIV 2);
LineTo(Image1.Width,Image1.Height DIV 2);
MoveTo(Image1.Width DIV 2,0);
LineTo(Image1.Width DIV 2,Image1.Height);
Brush.Color:=clGreen;
Rectangle(Image1.Width DIV 2 - 50, Image1.Height DIV 2 - 50,
Image1.Width DIV 2 + 50, Image1.Height DIV 2 + 50);
Brush.Color:=clRed;
Ellipse(Image1.Width DIV 2 - 10, Image1.Height DIV 2 - 10,
Image1.Width DIV 2 + 10, Image1.Height DIV 2 + 10);
END
end;
Разберемся, что здесь написано. Оператор WITH "выносит за скобки" слова Image1.Canvas, чтобы их не приходилось писать в каждой строчке. Команды Brush.Color и Pen.Color задают будущие цвета заливки и контура, соответственно. Сами цвета обозначаются по их имени, перед которым идут буквы cl, например, clWhite, clRed, clGreen. Команда FillRect рисует закрашенный прямоугольник. Здесь она применена для очистки всего поля рисования, поэтому в качестве прямоугольника задается тот прямоугольник, который занимает весь объект Image1. Он хранится в свойстве ClientRect. Проще говоря, команда FillRect(Image1.ClientRect)заливает весь холст цветом заливки.
Рисование отрезка от точки x1,y1 в точку x2,y2 выполняется пером в два этапа. Сначала перо командой MoveTo(x1,y1) позиционируется без проведения линии в начальную точку отрезка, а затем отрезок проводится командой LineTo(x2,y2). Координаты начал и концов отрезков показаны на рис. 2, они легко вычисляются. Не забывайте, что координаты на экране могут быть только целыми, поэтому надо использовать операцию целочисленного деления DIV.
Команда Rectangle рисует прямоугольник с заданными цветами контура и заливки. Прямоугольник задается координатами концов любой его диагонали. В нашем случае длина стороны прямоугольника будет 20 пикселов и он строится симметрично относительно середины холста.
Команда Ellipse строит окружности и эллипсы. Параметры ее немного необычны нужно указать координаты концов диагонали прямоугольника, в который будет вписан эллипс или окружность.
Порядок рисования фигур имеет значение. Если переставить местами команды Rectangle и Ellipse, то прямоугольник закроет собой окружность и вы ее никогда не увидите.
Помимо сплошной заливки, можно применять и другие ее виды (штриховка, точки и т.д.), меняя свойство Style объекта Brush:
Рис. 3 Способы заливки.
Значение bsSolid соответствует сплошной заливке, bsClear ее отсутствию, что позволяет рисовать незакрашенные фигуры.
Для линий свойство Pen.Style устанавливает вид линии:
psSolid |
сплошная линия |
psDash |
пунктирная линия |
psDot |
линия из точек |
psDashDot |
штрих пунктирная линия |
psDashDotDot |
линия "тире точка точка" |
psClear |
линия не рисуется (например, для построения объекта без контура) |
Если требуется провести прямую, получайте ее только по двум точкам.
Из законов Мэрфи
Одно из наиболее интересных применений графических средств Delphi построение графиков функций. Давайте нарисуем на экране синусоиду, которую мы вычисляли на прошлой лабораторной работе. Форма должна иметь вид, показанный на рис. 4.
Рис. 4 Форма программы построения графика функции.
Сама программа расчета не отличается от той, что мы делали в прошлый раз.
procedure TForm1.Button1Click(Sender: TObject);
VAR Xmin, Xmax, h, y : REAL;
cx,cy:REAL;
begin
TRY
Xmin:=StrToFLoat(LabeledEdit1.Text);
Xmax:=StrToFLoat(LabeledEdit2.Text);
h:=StrToFLoat(LabeledEdit3.Text)
EXCEPT
MessageDlg('Неверные данные', mtError, [mbOK],0);
Exit
END;
IF Xmax<=Xmin THEN
BEGIN
MessageDlg('Xmin>Xmax!', mtError, [mbOK],0);
Exit
END;
Memo1.Lines.Clear;
WITH Image1.Canvas DO
BEGIN
Brush.Color:=clBlue;
FillRect(Image1.ClientRect);
// Ось Х
Pen.Color:=clWhite;
MoveTo(0,Image1.Height DIV 2);
LineTo(Image1.Width, Image1.Height DIV 2);
cx:=(Xmax-Xmin)/Image1.Width;
cy:=2/Image1.Height;
IF cy>cx THEN
cx:=cy;
MoveTo(0,Image1.Height DIV 2); // начало графика
WHILE Xmin<=Xmax DO
BEGIN
y:=sin(xmin);
Memo1.Lines.Add('sin('+FloatToStrF(Xmin,ffFixed,10,4)+')='+
FloatToStrF(y,ffFixed,10,4));
LineTo(TRUNC(Xmin/cx),Image1.height DIV 2 - TRUNC(y/cx));
Xmin:=Xmin+h
END
END
end;
Остановимся на командах построения графика. Сначала мы заливаем весь холст синим цветом и проводим посередине горизонтальную белую линию это ось ОХ. Затем необходимо рассчитать масштабные коэффициенты по осям координат, чтобы при любых значениях Xmin, Xmax и h график уместился в окне. Для функции sin(x) очевидно, что по оси OY ее значения будут изменяться от 1 до 1, а по оси ОХ от Xmin до Xmax. Коэффициенты по осям будут равны:
;
Из этих двух коэффициентов нужно выбрать наибольший, тогда весь график гарантированно уместится на холсте. Далее для получения экранных координат текущие значения x и sin(x) надо разделить на рассчитанный ранее максимальный коэффициент. Наконец, при построении графика его надо сместить вниз на половину высоты холста, поскольку ось ОХ проходит посередине. Обратите внимание на использование функции TRUNC для получения целочисленных значений координат.
Рис. 5 Результат работы программы.
В задаче из N уравнений всегда будет N+1 неизвестная.
Из законов Мэрфи
Рассмотрим задачу построения треугольника с известными длинами сторон AB, AC, BC. подобное построение вызывает большие трудности, поскольку непонятно, с чего же начать? Сделаем следующее. Зафиксируем на холсте одну вершину треугольника в точке с произвольными координатами a1,b1. Будем считать, что одна из сторон идет горизонтально, что сразу дает нам координаты второй точки (рис. 6).
Рис. 6 Построение треугольника.
Осталось найти координаты точки С. Найдем косинус угла CAB по теореме косинусов: . Рассмотрим прямоугольный треугольник ACC1. В нем нам известны все углы и одна сторона. Тогда по теореме синусов , откуда находим dy. Аналогично вычисляем и dx.
Нет такой плохой ситуации, которая не могла бы стать еще хуже.
Из законов Мэрфи.
Было бы любопытно увидеть процесс постепенной отрисовки графика функции. График бы "полз", создавая иллюзию анимации. Попробуем поставить в цикл расчета функции команду задержки Sleep(100), останавливающую программу на 100мс:
. . .
WHILE Xmin<=Xmax DO
BEGIN
Sleep(100);
y:=sin(xmin);
. . .
Нажимаем F9 и… ничего не изменилось, только расчет стал выполняться медленнее, но график все равно отображается только в самом конце. Почему? Здесь мы столкнулись с одной важной особенностью программ на Delphi: при работе цикла никаких действий с элементами интерфейса не выполняется. Они как бы накапливаются и затем выполняются все сразу. Что же делать? Надо сказать Delphi, чтобы он не ленился и даже в цикле производил перерисовку нашего графика. Делается это просто достаточно в теле цикла записать команду Application.ProcessMessages. Вот теперь все получилось, график красиво "ползет".
Вероятность того, что бутерброд упадет маслом вниз,
прямо пропорциональна стоимости ковра.
Из законов Мэрфи.
Давайте изобразим звездное небо, по которому летит летающая тарелка. При этом нужно сделать настоящую анимацию с автоматическим восстановлением фона под движущейся картинкой.
Сначала нарисуем небо. Положите на форму Image и кнопку. При нажатии кнопки будет выполняться следующий код:
procedure TForm1.Button1Click(Sender: TObject);
VAR i:WORD;
begin
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
END
end;
Сначала весь холст заливается черным цветом, а затем на нем вы случайных местах отображаются 500 звезд. Для изображения отдельной точки можно использовать свойство объекта Canvas массив Pixels[x,y], обеспечивающий прямой доступ к цвету точки с координатами x,y.
Теперь надо нарисовать летающую тарелку. Их толком никто не видел, поэтому особой точности в деталях не требуется. Давайте вынесем команды рисования тарелки в отдельную процедуру, это заметно облегчит жизнь в дальнейшем.
procedure TForm1.Button1Click(Sender: TObject);
PROCEDURE Ufo(x,y:INTEGER);
BEGIN
WITH Image1.Canvas DO
BEGIN
Pen.Color:=clBlue;
Pen.Width:=3;
Ellipse(x,y,x+20,y+10)
END
END;
VAR i:WORD;
...
Обратите внимание, что процедура Ufo должна находиться внутри процедуры TForm1.Button1Click потому, что иначе она не будет иметь доступа к экранной форме Form1. Из-за особенностей работы с анимацией цвет летающей тарелки на экране будет вовсе не синим. Тарелка изобразится цветом, получающимся в результате выполнения операции "логическое ИЛИ" над цветом фона и изображения. В данном случае тарелка окажется желтого цвета, что вполне приемлемо.
Осталось организовать движение тарелки по экрану. Делается это примерно так:
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. Она устанавливает режим вывода графики "исключающее ИЛИ". При таком режиме вывод одной и той же картинки дважды в одно и то же место изображения приводит к автоматическому восстановлению фона под картинкой. В цикле картинка выводится первый раз (вызов процедуры Ufo), затем выполняется команда Application.ProcessMessages, обеспечивающая немедленное отображение НЛО на экране и делается задержка на 10мс, чтобы мы успели увидеть, что получилось. Далее НЛО выводится в то же самое место еще раз, при этом изображение тарелки пропадет, а под ней автоматически восстановится фон.
Координаты тарелки меняются и по Х, и по Y, поэтому она поедет по экрану вправо вниз.
Запускаем… Красиво? Нет! Экран безобразно мерцает. Что делать? Спокойно, это просто еще один фокус Delphi. Чтобы динамическое изображение на форме не мерцало, в начало процедуры вывода анимации надо добавить строчку
Form1.DoubleBuffered:=TRUE;
Вот теперь наш мультик будет смотреться вполне неплохо.
Вы уже дошли до состояния, когда у вас нет времени, чтобы
разрешить те проблемы, которые отнимают у вас все время?
Из законов Мэрфи
Интересная возможность Delphi создание процедур, автоматически выполняющихся через заданные промежутки времени. Для этого используется специальный объект Timer, находящийся на закладке System (). Этот объект невизуальный, он не отображается на форме во время работы программы и его можно разместить в любом ее месте.
Главное свойство объекта Timer называется Interval и задает время в миллисекундах, по истечении которого таймер вызывает процедуру, присоединенную к его событию OnTimer. Свойство Enabled включает и выключает таймер. Когда таймер включен, он постоянно и незаметно для пользователя отсчитывает время и, как только пройдет заданный интервал, выполняет заданную процедуру, затем снова начинает отсчитывать время и т.д.
Простейший пример работы таймера вывод в заголовке формы текущего времени. Настроим таймер так, чтобы он вызывал процедуру каждую секунду. Для этого свойство Interval нужно установить в 1000, а свойство Enabled в True. На закладке Events инспектора объектов дважды щелкам мышью в единственном поле OnTimer пишем следующее:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Form1.Caption:=TimeToStr(Now)
end;
Функция Now возвращает текущее время по часам компьютера в виде числа секунд, прошедшего с полуночи, а функция TimeToStr превращает ее в текстовую строку привычного нам вида вроде "15:25:18". Вот как просто решается на Delphi задача отображения часов на экране.
Когда ваш самолет опаздывает, самолет,
на который вы хотели пересесть, улетает вовремя.
Из законов Мэрфи
Заставим наше НЛО мигать менять цвет при движении при помощи таймера. Настроим таймер так, чтобы он срабатывал каждые 100мс. Для управления цветом заливки НЛО придется ввести глобальную переменную. Она описывается в начале программы после оператора implementation:
implementation
var clr:TColor=clGreen;
Обратите внимание на интересную особенность Delphi глобальным переменным можно задавать начальные значения. В нашем случае в переменную clr с самого начала будет занесено значение clGreen (код зеленого цвета). TColor это системный тип данных, предназначенный для хранения кодов цветов.
В процедуре таймера мы должны циклично менять значение переменной clr. Делается это так:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if clr=clGreen then
clr:=clYellow
else
clr:=clGreen
end;
Здесь в переменную clr будут циклически заноситься то значение clGreen, то clYellow.
Что делать дальше? Проблема в том, что в цикле процедура отрисовки НЛО вызывается дважды и оба раза она должна вызываться при одном и том же цвете НЛО, иначе не восстановится фон под картинкой и от нашей тарелки на экране останутся безобразные следы. Сделаем следующее: в процедуре TForm1.Button1Click заведем локальную переменную с типа TСolor и в нее будем запоминать текущее значение глобальной переменной clr в момент перед первым выводом тарелки на экран. Изменим и процедуру Ufo теперь в нее нужно будет передавать не только координаты, но и цвет заливки. Получается вот что:
procedure TForm1.Button1Click(Sender: TObject);
VAR i:WORD;
c:TColor;
PROCEDURE Ufo(x,y:INTEGER; c:TColor);
BEGIN
WITH Image1.Canvas DO
BEGIN
Brush.Color:=c;
Pen.Color:=clBlue;
Pen.Width:=3;
Ellipse(x,y,x+20,y+10)
END
END;
begin
Form1.DoubleBuffered:=TRUE;
WITH Image1.Canvas DO
BEGIN
Brush.Color:=clBlack;
Brush.Style:=bsSolid;
FillRect(Image1.ClientRect);
… // вывод звездного неба
Pen.Mode:=pmNOTXOR;
FOR i:=0 TO Image1.Width DO
BEGIN
c:=clr; // запомнили значение глобальной переменной clr
Ufo(i, i DIV 2,c);
Application.ProcessMessages;
Sleep(10);
Ufo(i, i DIV 2,c)
END
END
end;
Применение нескольких таймеров позволяет организовать анимацию нескольких объектов. Например, можно создать несколько блуждающих по экрану астероидов, от которых должна увертываться управляемая пользователем летающая тарелка.