delphi 个包含 TPictures 集合的组件

delphi component with a collection of TPictures

我正在尝试创建一个像 TImage 这样的 VCL 组件,它可以让我添加不同数量的不同大小的 TPicture。 目标是能够通过 属性 列表中的 VCL 编辑器分配该数量的 TPictures。

在这里我们得出结论,应该使用带有 TCollectionItems 的 TCollection。这就是我现在想要做的,但是在我结束编译器错误之前有很多次:"Published property 'Pictures' can not be of Type ARRAY" 在这一行中: property Pictures[Index: Integer]: TPic read GetPic write SetPic;

unit ImageMultiStates;

interface

uses
  Vcl.Graphics, Vcl.StdCtrls, System.SysUtils, System.Classes, Vcl.Controls, Vcl.ExtCtrls, Forms, Generics.Collections;

type

  TPic = class(TCollectionItem)
  private
    FPicture: TPicture;
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
  published
    property Picture: TPicture read FPicture write FPicture;
  end;

  TPictures = class(TCollection)
  private
    function GetPic(Index: Integer): TPic;
    procedure SetPic(Index: Integer; APicture: TPic);
  public
    constructor Create;
  published
    property Pictures[Index: Integer]: TPic read GetPic write SetPic;
  end;

  TImageMultiStates = class(TImage)
  private
    FPictures: TPictures;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Activate(Index: Integer);
  end;

procedure Register;

implementation

constructor TPic.Create(Collection: TCollection);
begin
  inherited Create(Collection);
end;

destructor TPic.Destroy;
begin
  FPicture.Free;
  inherited Destroy;
end;

procedure TPic.Assign(Source: TPersistent);
begin
  FPicture.Assign(Source);
end;


constructor TPictures.Create;
begin
  inherited Create(TPic);
end;

procedure TPictures.SetPic(Index: Integer; APicture: TPic);
begin
  Items[Index].Assign(APicture);
end;

function TPictures.GetPic(Index: Integer): TPic;
begin
  Result := TPic(inherited Items[Index]);
end;


constructor TImageMultiStates.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

destructor TImageMultiStates.Destroy;
begin
  FPictures.Free;
  inherited Destroy;
end;

procedure TImageMultiStates.Activate(Index: Integer);
begin
  Picture.Assign(FPictures.Items[Index]);
end;

procedure Register;
begin
  RegisterComponents('Standard', [TImageMultiStates]);
end;

end.

似乎没有人预料到会抛出这个错误,可能与我安装的组件有关?我使用内部的 GetIt Package-Manager 来安装 Jedi Code Library 2.8、Jedi Visual Component Library 和 PNGComponents 1.0。我想就 TImage 相关组件而言就是这样。也许其中之一用时髦的东西覆盖了我的一些 TImage 内容...

您的索引 属性 使用的语法看起来像 return 是一个数组,但它并没有这样做。 pictures 属性 return 是一个索引 TPic。它一次只能return一个TPic

如果你想return一个数组,你必须这样说:

function GetPictures: TArray<TPicture>;
procedure SetPictures(const value: TArray<TPicture>);
property Pictures: TArray<TPicture> read GetPictures write SetPictures;  

//GetPictures might look something like this:
function TMyClass.GetPictures: TArray<TPicture>;
var
  i: integer;
begin
  SetLength(Result, Self.FPictureCount);
  for i:= 0 to FPictureCount - 1 do begin
    Result[i]:= GetMyPicture[i];
  end;
end;

我不确定你的 TPic collection 是如何工作的,所以你必须调整它以满足你的需要。
显然,如果您愿意,可以使用 TArray<TArray<TPicture>>(又名:array of array of TPicture)。

我做了一些实验,从 TPanel 中导出了 TPicturePanel。它有一个 Pictures 属性,它是 TPicturesTOwnedCollection 的后代并且包含 TPics。每个 TPic 都有一个 Picture 属性。我可以安装此组件,它允许我使用所谓的 集合编辑器 编辑 Pictures 集合,它允许您添加或删除 TPic 实例。如果你在Collection editor中select一个TPic,你可以给它Picture属性分配一张图片,即从文件加载等

这是 TPicturePanel 的工作代码。您可以在此之后为您的组件建模:

unit PicturePanels;

interface

uses
  System.SysUtils, System.Classes, Vcl.Controls, Vcl.ExtCtrls, Vcl.Graphics;

type
  TPic = class(TCollectionItem)
  private
    FPicture: TPicture;
    procedure SetPicture(const Value: TPicture);
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(AOwner: TCollection); override;
    destructor Destroy; override;
  published
    property Picture: TPicture read FPicture write SetPicture;
  end;

  TPictures = class(TOwnedCollection)
  private
    function GetItem(Index: Integer): TPic;
    procedure SetItem(Index: Integer; const Value: TPic);
  public
    constructor Create(AOwner: TPersistent);
    property Items[Index: Integer]: TPic read GetItem write SetItem;
  end;

  TPicturePanel = class(TPanel)
  private
    FPictures: TPictures;
    procedure SetPictures(const Value: TPictures);
  published
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Pictures: TPictures read FPictures write SetPictures;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TPicturePanel]);
end;

{ TPicturePanel }

constructor TPicturePanel.Create(AOwner: TComponent);
begin
  inherited;
  FPictures := TPictures.Create(Self);
end;

destructor TPicturePanel.Destroy;
begin
  FPictures.Free;
  inherited;
end;

procedure TPicturePanel.SetPictures(const Value: TPictures);
begin
  FPictures.Assign(Value);
end;

{ TPic }

procedure TPic.Assign(Source: TPersistent);
begin
  inherited;
  if Source is TPic then
    FPicture.Assign(TPic(Source).FPicture);
end;

constructor TPic.Create(AOwner: TCollection);
begin
  inherited;
  FPicture := TPicture.Create;
end;

destructor TPic.Destroy;
begin
  FPicture.Free;
  inherited;
end;

procedure TPic.SetPicture(const Value: TPicture);
begin
  FPicture.Assign(Value);
end;

{ TPictures }

constructor TPictures.Create(AOwner: TPersistent);
begin
  inherited Create(AOwner, TPic);
end;

function TPictures.GetItem(Index: Integer): TPic;
begin
  Result := inherited GetItem(Index) as TPic;
end;

procedure TPictures.SetItem(Index: Integer; const Value: TPic);
begin
  inherited SetItem(Index, Value);
end;

end.