我正在构建一个自定义 OpenGL 控件,它包含一个项目列表,其中每个项目可能是一个不同的类,但继承自某个公共类类型。我不知道如何以一种可以循环遍历这些项目并执行某些操作的方式来执行此操作,这些操作预计将在继承的类中被覆盖。
更具体地说,这是要绘制到画布上的视觉对象列表。我有一个通用类TGLItem
,用于创建许多继承类。例如,TGLCar
继承自TGLItem
并添加到列表中TGLItems
。此自定义列表类是控件的一部分。
当控件绘制时,它会循环遍历这个项目列表并调用Draw
每个项目的过程。Draw
旨在被实际绘制项目的继承类覆盖。所以真正的工作是从类Draw
中实现的过程中完成的,TGLCar
但它只能从主控件中调用。
主控件 ( TGLImage
) 不知道实际继承的项目是什么,但能够调用它的Draw
过程,期望它绘制到 OpenGL。
如何以适应这种情况的方式构建此项目列表和项目库?这是我到目前为止所拥有的:
TGLItems = class(TPersistent)
private
FItems: TList;
function GetItem(Index: Integer): TGLItem;
procedure SetItem(Index: Integer; const Value: 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 = class(TPersistent)
private
FPosition: TGLPosition;
FDimensions: TGLDimensions;
FOwner: TGLItems;
FItemClass: TGLItemClass;
procedure PositionChanged(Sender: TObject);
procedure DimensionsChanged(Sender: TObject);
procedure SetPosition(const Value: TGLPosition);
procedure SetDimensions(const Value: TGLDimensions);
public
constructor Create(Owner: TGLItems);
destructor Destroy; override;
procedure Draw;
property Owner: TGLItems read FOwner;
property ItemClass: TGLItemClass read FItemClass;
published
property Position: TGLPosition read FPosition write SetPosition;
property Dimensions: TGLDimensions read FDimensions write SetDimensions;
end;
执行...
{ TGLItem }
constructor TGLItem.Create;
begin
FPosition:= TGLPosition.Create;
FPosition.OnChange:= PositionChanged;
FDimensions:= TGLDimensions.Create;
FDimensions.OnChange:= DimensionsChanged;
end;
destructor TGLItem.Destroy;
begin
FPosition.Free;
FDimensions.Free;
inherited;
end;
procedure TGLItem.DimensionsChanged(Sender: TObject);
begin
end;
procedure TGLItem.Draw;
begin
//Draw to gl scene
end;
procedure TGLItem.PositionChanged(Sender: TObject);
begin
end;
procedure TGLItem.SetDimensions(const Value: TGLDimensions);
begin
FDimensions.Assign(Value);
end;
procedure TGLItem.SetPosition(const Value: TGLPosition);
begin
FPosition.Assign(Value);
end;
{ TGLItems }
procedure TGLItems.Add(AItem: TGLItem);
begin
FItems.Add(AItem);
//Expects objects to be created and maintained elsewhere
//This list object will not create/destroy any items
end;
function TGLItems.Count: Integer;
begin
Result:= FItems.Count;
end;
constructor TGLItems.Create;
begin
FItems:= TList.Create;
end;
destructor TGLItems.Destroy;
begin
FItems.Free;
inherited;
end;
function TGLItems.GetItem(Index: Integer): TGLItem;
begin
Result:= TGLItem(FItems[Index]);
end;
procedure TGLItems.SetItem(Index: Integer; const Value: TGLItem);
begin
TGLItem(FItems[Index]).Assign(Value);
end;
它的 OpenGL 部分在这种情况下不一定相关,我只是想解释一下它的目的是什么,以便了解我期望它如何工作。
我也有将TGLItems
列表对象传递给其构造函数中的每个单独项目的想法,并让每个项目在项目列表中注册其自身。在这种情况下,项目列表将没有任何添加过程,我什至可能不需要单独的列表对象。我只是确定应该有一些我缺少的大技巧,并且我愿意对结构进行任何大规模更改以更有效地适应这一点。