Ещё раз напомним, как должен выглядеть компонент «Светофор» после запуска программы:
А теперь ещё раз посмотрим, как выглядит класс «TSvetofor»:
unit Svetofor;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs,ExtCtrls,StdCtrls;
type
TSvetofor=class(TWinControl)
private
Interval:integer;
num:integer;
LB:TListBox;
btStop,btGO:TButton;
fShape1,fShape2,fShape3,fShape4,fShape5,fShape6,fShape7:TShape;
fTm1,fTm2,fTm3,fTm4:TTimer;
fGPan,fPan1,fPan2:TPanel;
fImage:TImage;
procedure Stop;
procedure btStopOnClick(Sender: TObject);
procedure work;
procedure btGOOnClick(Sender: TObject);
procedure fTm1Timer(Sender: TObject);
procedure fTm2Timer(Sender: TObject);
procedure fTm3Timer(Sender: TObject);
procedure fTm4Timer(Sender: TObject);
procedure LbDblClick(Sender: TObject);
function prGet():TPanel;
procedure prSet(value:TPanel);
property pPan:TPanel read prGet write prSet;
public
Программное создание компонент TPanel, TShape, TImage, TTimer, TListBox, TButton.
Реализация конструктора.
constructor create(tc:TComponent); //описание конструктора помещёно в секции «public», так как конструктор должен быть виден за пределами модуля. Все остальные элементы класса будут не видны из других модулей.
end;
Итак, как мы говорили ранее, все элементы светофора создаются в конструкторе
constructor TSvetofor.create(tc:TComponent);
begin
inherited create(tc); //вызываем все унаследованные конструкторы.
self.Interval:=2000; //устанавливаем начальный интервал — время, в течение которого горит красный сигнал светофора
Замечание 1 . К тому моменту, когда происходит обращение к конструктору «Tsvetofor.create», объект «светофор» уже создан, его свойство «self» заполнено и указывает на объект «vSvetofor».
Замечание 2. Так как «self» автоматически добавляется к каждому полю и свойству класса, то его можно и не прописывать в явном виде. Записи «self.Interval:=2000;» и «Interval:=2000;» будут эквивалентны.
self.num:=1; //номер фонаря, который будет зажжен в момент запуска программы (1-красный, 2- жёлтый, 3-зелёный, 4-стрелка)
Создание панелей
fGPan:=TPanel.Create(self); //создать главную панель
fGPan.Parent:=(tc as tWinControl); //отобразить панель (путём назначения ей «родителя»). Так как через «tc» передаётся ссылка на форму, то «родителем» будет «Form1»
with fGPan do //Чтобы не писать каждый раз fGPan.Top, fGPan. Width и так далее, применяют оператор «with … end»
begin
top:=10; left:=10; //задаём положение левого верхнего угла панели
width:=450; height:=450; //задаём ширину и высоту панели
color:=clOlive; //цвет панели
name:=’fGPan’; //имя панели
end;
fPan1:=TPanel.Create(self); //создаём первую панель для светофора. Владельцем назначен объект «Svetofor» (ссылка «self»).
fPan1.Parent:=fGPan; //родителем назначена главная панель. Отображение «fPan1» будет располагаться в пределах этой панели. Все сообщения операционной системы также будут приходить от этого оконного элемента.
with fPan1 do
begin
Top:=10; left:=10;
width:=185; height:=350;
color:=clAppWorkSpace;
name:=’fPan1′;
caption:=»; //заголовок
end;
fPan2:=TPanel.Create(self);
fPan2.Parent:=fGPan;
with fPan2 do
begin
Top:=240; left:=10+185;
width:=165; height:=120;
color:=clAppWorkSpace;
name:=’fPan2′;
caption:=»;
end;
Создание геометрической фигуры.
fShape1:=TShape.Create(self); //создание геометрического элемента
fShape1.Parent:=fPan1; //отображение элемента будет в пределах первой панели
with fShape1 do
begin
Top:=24-5; width:=100;
Shape:=stCircle; //геометрическим элементом будет окружность.
left:=40; height:=100;
brush.Style:=bsDiagCross; //тип кисти, закрашивающей элемент — косая перекрёстная штриховка
brush.color:=clBlue; //цвет кисти (в данном случае — линий штриховки)
end;
fShape2:=TShape.Create(self);
fShape2.Parent:=fPan1;
with fShape2 do
begin
Top:=132-5; width:=100; Shape:=stCircle; left:=40; height:=100;
brush.color:=clBlue; brush.Style:=bsDiagCross;
end;
fShape3:=TShape.Create(self);
fShape3.Parent:=fPan1;
with fShape3 do
begin
Top:=240-5; width:=100; Shape:=stCircle; left:=40; height:=100;
brush.color:=clBlue; brush.Style:=bsDiagCross;
end;
fShape4:=TShape.Create(self);
fShape4.Parent:=fPan2; //отображение элемента будет в пределах второй панели
with fShape4 do
begin
Top:=10; width:=100; Shape:=stCircle; left:=35; height:=100;
brush.color:=clBlue; brush.Style:=bsDiagCross;
end;
fShape5:=TShape.Create(self);
fShape5.Parent:=fPan1;
with fShape5 do
begin
Top:=24-5; width:=100; Shape:=stCircle; left:=40; height:=100;
brush.color:=clRed;
brush.Style:=bsSolid; //закраска «сплошной» кистью (сплошная заливка)
visible:=false; //в момент создания объекта «svetofor» элемент будет скрыт (невидим)
end;
fShape6:=TShape.Create(self);
fShape6.Parent:=fPan1;
with fShape6 do
begin
Top:=132-5; width:=100; Shape:=stCircle; left:=40; height:=100;
brush.color:=clYellow; brush.Style:=bsSolid; visible:=false;
end;
fShape7:=TShape.Create(self);
fShape7.Parent:=fPan1;
with fShape7 do
begin
Top:=240-5; width:=100; Shape:=stCircle; left:=40; height:=100;
brush.color:=clGreen; brush.Style:=bsSolid; visible:=false;
end;
Создание компонента Image для отображения стрелки
fImage:=TImage.Create(self); //создание компонента «Image», на канве которого будет нарисована стрелка
fImage.Parent:=fPan2;
with fImage do //рисуем стрелку
begin
Top:=10; Left:=35; //координаты «fImage» по отношению к родителю
Width:=100;Height:=100;
Canvas.MoveTo(10,35); //помещаем «перо», которым рисуем линию, в точку с координатами (10,35) по отношению к левому верхнему углу компонента «fImage»
Canvas.LineTo(60,35); //рисуем линию от предыдущей точки в точку (60,35). Цвет и толщина пера установлены по умолчания (черный, 1 пиксел)
Canvas.LineTo(60,20); Canvas.LineTo(90,50);
Canvas.LineTo(60,80); Canvas.LineTo(60,65);
Canvas.LineTo(10,65);
Canvas.LineTo(10,35); //замыкаем контур
Canvas.Brush.Color:=clGreen; //устанавливаем цвет кисти «зелёный» (стиль кисти берётся по умолчанию — сплошная заливка)
Canvas.FloodFill(50,50,clWhite,fsSurface); //замкнутый контур, содержащий внутреннюю точку (50,50), будет закрашен текущей кистью (зелёным цветом). Параметр «fsSurface» указывает, что закраска точек останавливается на контуре, цвет точек которого отличен от цвета точки (50,50). Параметр «clWhite» указывает, что будут закрашены все точки с цветом «clWhite» внутри контура.
Canvas.Brush.Color:=clAppWorkSpace; //цвет панели
Canvas.FloodFill(10,10,clWhite,fsSurface); //закрашиваем все точки канвы снаружи от стрелки
SendToBack; //делаем слой, на котором размещён компонент «fImage», самым нижним. Теперь поверх него будет слой с компонентом «shape»
visible:=false; //начальное состояние компонента — невидим.
end;
В результате получим изображение стрелки:
Создание компонента «Таймер»
fTm1:=TTimer.Create(self); //создаём таймеры
fTm2:=TTimer.Create(self);
fTm3:=TTimer.Create(self);
fTm4:=TTimer.Create(self);
fTm1.Enabled:=false; //выключаем отсчёт таймера.
fTm2.Enabled:=false;
fTm3.Enabled:=false;
fTm4.Enabled:=false;
fTm1.Interval:=Interval;// задаём интервал времени, по истечению которого наступает событие «onTimer»
fTm2.Interval:=(Interval div 10)*6; //так как «Interval» — целочисленное значение, то применяем к нему целочисленные арифметические операторы.
fTm3.Interval:=(Interval div 10)*15;
fTm4.Interval:=(Interval div 10)*5;
fTm1.OnTimer:= fTm1Timer; //назначаем событию «OnTimer» метод «Tm1Timer» в качестве обработчика этого события.
fTm2.OnTimer:= fTm2Timer;
fTm3.OnTimer:= fTm3Timer;
fTm4.OnTimer:= fTm4Timer;
Создание компонента «Список строк»
LB:=TListBox.Create(self); //создаем список строк
LB.Parent:=fGPan;
with LB, items do
begin
top:=16;left:=210; height:=200;
font.Size:=16;
Add(‘1000’); //добавляем строки в список
Add(‘2000’); Add(‘3000’); Add(‘4000’);
Add(‘5000’); Add(‘6000’); Add(‘7000’); Add(‘8000’);
end;
LB.OnDblClick:=LbDblClick; //назначаем обработчик события двойного клика по строке списка.
Создание кнопок
btStop:=TButton.Create(self); //создаём кнопку
btStop.Parent:=fGPan;
btStop.OnClick:=btStopOnClick; //назначаем обработчик события клика по кнопке.
with btStop do
begin
top:=400; left:=50; caption:=’СТОП’;
end;
btGO:=TButton.Create(fGPan);
btGO.Parent:=fGPan;
btGO.OnClick:=btGOOnClick;
with btGO do
begin
top:=400; left:=50+150; caption:=’GO’;
end;
work; //вызываем метод «work», отвечающий за последовательность включения фонарей светофора
end;
***
Продолжение в следующей статье.