В статье рассматривается задача создания настраиваемого OpenGL-контроля в Delphi, который состоит из списка элементов, каждый из которых может быть различного класса, но унаследованного от общего класса. Цель состоит в том, чтобы иметь возможность пройтись по этому списку и выполнить определенные действия, которые ожидается, что они будут переопределены в унаследованных классах.
Более конкретно, это список визуальных объектов, которые должны быть нарисованы на канвасе. Есть общий класс TGLItem, который используется для создания нескольких унаследованных классов, таких как TGLCar, которые добавляются в список TGLItems. При рисовании контроль проходит по этому списку и вызывает процедуру Draw каждого элемента. Процедура Draw предназначена для переопределения в унаследованных классах, где и происходит фактическое рисование элемента.
Основной контроль (TGLImage) не должен знать, какой именно унаследованный элемент находится в списке, но должен иметь возможность вызывать его процедуру Draw, ожидая, что она нарисует на OpenGL.
Решением этой проблемы является использование полиморфизма. Класс TGLItem должен быть объявлен как абстрактный класс с виртуальной процедурой Draw. Каждый унаследованный класс должен переопределить процедуру Draw и реализовать рисование своего элемента. При рисовании контроля он просто проходит по списку элементов и вызывает процедуру Draw каждого элемента. Благодаря полиморфизму, будет вызвана правильная версия процедуры Draw в зависимости от типа унаследованного класса элемента.
Вот пример кода, демонстрирующий это решение:
program OpenGLControl;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Vcl.Graphics,
Gl;
type
TGLItem = class
private
FPosition: TGLPosition;
FDimensions: TGLDimensions;
FOwner: TGLItems;
FItemClass: TGLItemClass;
protected
procedure Draw; abstract;
public
constructor Create(Owner: TGLItems);
property Owner: TGLItems read FOwner;
property ItemClass: TGLItemClass read FItemClass;
end;
TGLCar = class(TGLItem)
protected
procedure Draw; override;
end;
TGLItems = class
private
FItems: TList<TGLItem>;
public
constructor Create;
destructor Destroy; override;
procedure Add(AItem: TGLItem);
function Count: Integer;
property Items[Index: Integer]: TGLItem read GetItem write SetItem; default;
end;
{ TGLItem }
constructor TGLItem.Create(Owner: TGLItems);
begin
FOwner := Owner;
// Initialize other properties
end;
procedure TGLItem.Draw;
begin
// Base implementation, if any
end;
{ TGLCar }
procedure TGLCar.Draw;
begin
// Draw the car using OpenGL
end;
{ TGLItems }
constructor TGLItems.Create;
begin
FItems := TList<TGLItem>.Create;
end;
destructor TGLItems.Destroy;
begin
FItems.Free;
inherited;
end;
procedure TGLItems.Add(AItem: TGLItem);
begin
FItems.Add(AItem);
end;
function TGLItems.Count: Integer;
begin
Result := FItems.Count;
end;
function TGLItems.GetItem(Index: Integer): TGLItem;
begin
Result := FItems[Index];
end;
procedure TGLItems.SetItem(Index: Integer; const Value: TGLItem);
begin
FItems[Index] := Value;
end;
var
Items: TGLItems;
Car: TGLCar;
begin
Items := TGLItems.Create;
try
Car := TGLCar.Create(Items);
try
Items.Add(Car);
// Add more items here, if needed
// Draw all items
for var Item in Items.Items do
Item.Draw;
finally
Car.Free;
end;
finally
Items.Free;
end;
end.
При таком подходе основной контроль не знает, какие именно унаследованные элементы находятся в списке, но может вызвать их процедуру Draw, ожидая, что она нарисует на OpenGL. Каждый унаследованный класс ответственен за правильное рисование своего элемента в переопределенной процедуре Draw.
Статья описывает задачу создания настраиваемого OpenGL-контроля в Delphi, состоящего из списка элементов, каждый из которых может быть различного класса, но унаследованного от общего класса. Решение задачи основано на полиморфизме, где общий класс `TGLIte
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.