I'm trying to create a VCL component like TImage, that lets me add a variable amount of different sized TPictures. The Goal is to be able to assign that number of TPictures through the VCL editor in the property list.
delphi component property: TObjectList<TPicture> here we came to the conclusion, that a TCollection with TCollectionItems should be used. This is what I'm trying to do now, but as many times before i end up with the compiler error: "Published property 'Pictures' can not be of Type ARRAY" in this line:
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.
Since noone seems to expect this error to be thrown, maybe it's related to my installed components? I used the internal GetIt Package-Manager to install the Jedi Code Library 2.8, Jedi Visual Component Library and PNGComponents 1.0. I guess that's about it as far as TImage-related components are concerned. Maybe one of these overrides some of my TImage contents with funky stuff...
I experimented a little and derived a TPicturePanel
from TPanel
. It has a Pictures
property, which is a TPictures
, a descendant of TOwnedCollection
and which contains TPics
. Each TPic
has a Picture
property. I can install this component, and it allows me to edit the Pictures
collection using the so called Collection editor, which allows you to add or remove TPic
instances. If you select a TPic
in the Collection editor, you can assign a picture to its Picture
property, i.e. load from file, etc.
Here is the working code for TPicturePanel
. You can model your component after this:
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.