Программа «Светофор» как объект. Часть 2.

Внешний вид.

В отличие от первого примера создания «Светофора», во втором примере после запуска программы будут отображены только две кнопки: «Создать светофор» и «Очистить память».

Кнопка «Создать светофор» создаёт экземпляр объекта типа «TSvetofor».

Кнопка «Очистить память» удаляет из памяти экземпляр объекта типа «TSvetofor».

После нажатия на кнопку «Создать светофор» должно появиться следующее изображение (за исключением поясняющих стрелок):

светофор

Выделим элементы этого изображения:

  • Панель, на которой расположены все остальные элементы — панель оливкового цвета fGPan (главная панель) типа TPan.

На ней находятся:

  • Панель, на которой расположены три фонаря светофора — серая панель fPan1 типа TPan.
  • Панель, на которой расположена дополнительная стрелка светофора — серая панель fPan2 типа TPan.
  • Список строк LB типа TListBox.
  • Кнопка «Стоп» — останавливает работу светофора, «выключая» его (то есть переводит «светофор» в состояние, изображённое на рисунке).
  • Кнопка «GO» — запускает работу «светофора»

На панели fPan1 расположены три фигуры — компоненты типа «TShape». Это экземпляры fShape1, fShape2 и fShape3. Этот компонент может отображать различные фигуры, в том числе — окружности. Поверхность окружности может быть оформлена с помощью разных заливок. Зажжённый фонарь будем оформлять в виде сплошной заливки, а выключенный — с помощью косой штриховки.

Компоненты fShape1, fShape2, fShape3 и fShape4 будут заштрихованы. Поверх компонент fShape1, fShape2 и fShape3 расположим компоненты fShape5, fShape6, fShape7, имеющими сплошную заливку.

Поверх fShape4 расположим компонент типа TImage, на поверхности которого нарисуем зелёную стрелку.

Создание экземпляра объекта «TSvetofor»

В предыдущей статье мы рассмотрели основные принципы объявления пользовательского класса «TSvetofor»:

type
TSvetofor=class(TWinControl)
public
constructor create(tc:TComponent);
private
end;

implementation

constructor Tsvetofor.create(tc:TComponent);
begin
inherited create(tc);
end;

Продолжим рассмотрение его дальнейшего формирования.

Вспомним, что изображение «светофора» на форме должно появиться сразу после клика по кнопке «Создать светофор» и автоматически начать работать.

Организуем создание экземпляра объекта «TSvetofor» в обработчике клика кнопки «button1Click»:

unit Unit1;
interface

var
Form1: TForm1;
implementation
uses Svetofor;
{$R *.dfm}
var
vSvetofor:TSvetofor;

procedure TForm1.Button1Click(Sender: TObject);
begin
vSvetofor:=TSvetofor.create(self);
vSvetofor.parent:=self;
vSvetofor.Activ(vSvetofor);
end;

Обратите внимание, что переменная «vSvetofor» объявлена в секции «implementation», после предложения «uses Svetofor;». Если переменную объявить в секции «interface», то мы не сможем обратиться к типу «TSvetofor», так как доступ к модулю «uses Svetofor» ещё не объявлен.

В принципе,возможно объявить «uses Svetofor;» в секции «interface» , но нежелательно. Это допустимо, если из модуля «Svetofor» нет обращений к модулю «Unit1». В противном случае возникнет циклическая ссылка, что приведёт к фатальной ошибке.

Обратите внимание, что ссылка на владельца производится указанием свойства «self» класса «TForm». Это свойство инициализируется автоматически в момент создания формы.

Поскольку «self» является свойством класса, то оно доступно внутри методов этого класса, в частности — внутри обработчиков событий.

Button1Click является обработчиком события, объявленным в классе «Tform». Поэтому после создания экземпляра «Form1» свойство «self» будет содержать ссылку на «Form1». То есть, например, операторы Form1.Name и Self.Name тождественны.

Теперь рассмотрим создание компонент, из которых состоит «светофор». Так как все элементы светофора мы располагаем на панели-основании, то в первую очередь создадим эту панель.

Создание объекта «Svetofor».

Объект «Svetofor» создаётся путём применения следующих операторов:

vSvetofor:=TSvetofor.create(self); //создаём экземпляр объекта
vSvetofor.Parent:=self; //назначаем «родителя» созданному объекту

Но сам по себе этот объект ещё ничего не делает и ничего из себя не представляет. Он даже невидим.

Чтобы наполнить его содержанием, дополним класс «TSvetofor» полями и методами, которые и создадут внешний вид «светофора», а затем заставят его работать.

Окончательный вид класса «TSvetofor» будет следующий:

type
Tsvetofor=class(TWinControl)
private
Interval:integer;
num:integer;
LB:TListBox;
btStop,btGO:TButton;
fGPan,fPan1,fPan2:TPanel;
fShape1,fShape2,fShape3,fShape4,fShape5,fShape6,fShape7:TShape;
fTm1,fTm2,fTm3,fTm4:TTimer;
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

constructor create(tc:TComponent); //создаёт экземпляр объекта. Ссылка на объект записывается в //переменную vSvetofor
procedure Activ(tc:TComponent); //создаёт все компоненты, из которых состоит «светофор»

end;

Базовые элементы класса и конструктора.

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

Для создания панели-основания (и панелей-элементов «светофора») объявим поля типа «TPanel» в классе «TSvetofor«:

TSvetofor=class(TWinControl)
public
constructor create(tc:TComponent);
private
Interval:integer; //здесь будет храниться значение интервала таймера
num:integer; //поле для хранения номера зажжённого фонаря светофора
obj:TComponent; //поле для хранения ссылки на объект «Светофор». //Заполняется после создания экземпляра объекта«Tsvetofor»
fGPan,fPan1,fPan2:TPanel; //поля fPan1 и fPan2 нужны для формирование панелей, на которых расположены непосредственно фонари «светофора».
end;

constructor Tsvetofor.create(tc:TComponent); //через «tc» передаётся ссылка на объект «Form1»
begin
inherited create(tc); //вызываются все унаследованные (родительские) конструкторы (начиная от TwinControl и вверх до TObject)
Interval:=2000; //начальное значение поля «Interval»
num:=1; //начальное значение поля «num»
end;

Замечание. Конструктор принимает аргумент, тип которого не ниже «TComponent».

Создание компонент, составляющих «светофор».

Далее будет показано, как в конструкторе будут создаваться эти компоненты, а именно:

  1. панель fGPan, лежащая на форме;
  2. две панели fPan1 и fPan2, из которых составлено изображение корпуса светофора
  3. Компоненты fShape1,fShape2,fShape3,fShape4 — геометрические фигуры. В нашем случае окружности (свойству «shape» будет задано значение «stCircle»). Они будут символизировать фонари в выключенном состоянии.
  4. Компоненты fShape5,fShape6,fShape7 — фонари красного, желтого и зеленого цвета.
  5. Компонент fImage — компонент для отображения растровых изображений. Имеет свойство «Canvas», с помощью которого можно программно рисовать на поверхности компонента типа «Timage».
  6. Невизуальные (неотображаемые) компонеты fTm1,fTm2,fTm3,fTm4 — таймеры, управляющие выключением фонарей.
  7. Компонент «TlistBox» (список строк) — с его помощью можно будет выбирать разные значения для задания интервала таймера.
  8. кнопка «Пуск» (caption “GO”) и кнопка «Стоп» («включение» и «выключение» светофора).

***

Продолжение описания работы программы «Светофор» в следующей статье.

Обновлено: 01.06.2021 — 10:48

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *