带有TPictures集合的delphi组件

时间:2016-07-21 14:34:32

标签: delphi vcl

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

delphi component property: TObjectList<TPicture>我们在这里得出结论,应该使用TCollection和TCollectionItems。这就是我现在要做的事情,但在我最终遇到编译错误之前很多次:&#34;已发布的属性&#39;图片&#39;不能是ARRAY类型&#34;在这一行:     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包管理器来安装Jedi代码库2.8,Jedi Visual Component Library和PNGComponents 1.0。就与TImage相关的组件而言,我想这是关于它的。也许其中一个用一些时髦的东西覆盖我的一些TImage内容......

2 个答案:

答案 0 :(得分:3)

我进行了一些实验并从TPicturePanel派生了一个TPanel。它有一个Pictures属性,TPicturesTOwnedCollection的后代,包含TPics。每个TPic都有Picture个属性。我可以安装此组件,它允许我使用所谓的集合编辑器编辑Pictures集合,它允许您添加或删除TPic个实例。如果您在收藏编辑器中选择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.

答案 1 :(得分:0)

您的索引属性使用看起来像返回数组的语法,但它不会这样做。 pictures属性返回索引TPic。它一次只能返回一个TPic

如果你想返回一个数组,你必须这么说:

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系列是如何工作的,因此您必须根据自己的需要进行调整 如果你愿意的话,显然你可以拥有TArray<TArray<TPicture>>(又名:array of array of TPicture)。