Class 作为属性的自定义类的数组

Class 作为属性的自定义类的数组,class,delphi,components,Class,Delphi,Components,我试图使用自定义类的数组作为组件的属性,但问题是这些值没有保存到组件中,这意味着如果我设置值,保存所有内容并再次打开项目,组件的值将消失。。。我的代码如下所示: unit Unit1; interface uses Windows, ExtCtrls,Classes,Controls; type TMyClass=class(TPersistent) private FName: string; FValue: double; public prop

我试图使用自定义类的数组作为组件的属性,但问题是这些值没有保存到组件中,这意味着如果我设置值,保存所有内容并再次打开项目,组件的值将消失。。。我的代码如下所示:

unit Unit1;

interface

uses  Windows, ExtCtrls,Classes,Controls;

type

  TMyClass=class(TPersistent)
  private
    FName: string;
    FValue: double;
  public
    property Name: string read FName write FName;
    property Value: double read FValue write FValue;
  end;

  TMyComponent= class(TCustomPanel)
  private
    FMyArray: array[0..200] of TMyClass;

    function GetmyArray(Index: Integer): TMyClass;

    procedure SetMyArray(index: Integer; Value: TMyClass);
  public
    property myArray[index: Integer]: TMyClass read GetMyArray write SetMyArray;
  end;

implementation

function TMyComponent.GetmyArray(Index: Integer): TMyClass;
begin
  result:= FmyArray[Index];
end;

procedure TMyComponent.SetMyArray(index: Integer; Value: TMyClass);
begin
  FMyArray[index].FName:= Value.FName;
  FMyArray[index].FValue:= Value.FValue;
end;

end.
MyArray1.parent:= MyComponent1;
MyArray2.parent:= MyComponent2;
...
我知道只有已发布的属性才能流式传输,但问题是我的属性是数组,无法发布。。。 我的建议是使用
DefineProperties()
来提供自定义流,但我不知道如何使用数组来实现这一点。 我认为的另一种可能性是将TMyClass修改为一种类,TMyComponent可以是它的父类,就像在TChart中所做的那样,您可以向它添加不同的系列类。但我不知道这是什么课

TMyClass=class(T???????????)
这样,我就可以取出属性MyArray并创建TMyClass并添加到TMyComponent,如下所示:

unit Unit1;

interface

uses  Windows, ExtCtrls,Classes,Controls;

type

  TMyClass=class(TPersistent)
  private
    FName: string;
    FValue: double;
  public
    property Name: string read FName write FName;
    property Value: double read FValue write FValue;
  end;

  TMyComponent= class(TCustomPanel)
  private
    FMyArray: array[0..200] of TMyClass;

    function GetmyArray(Index: Integer): TMyClass;

    procedure SetMyArray(index: Integer; Value: TMyClass);
  public
    property myArray[index: Integer]: TMyClass read GetMyArray write SetMyArray;
  end;

implementation

function TMyComponent.GetmyArray(Index: Integer): TMyClass;
begin
  result:= FmyArray[Index];
end;

procedure TMyComponent.SetMyArray(index: Integer; Value: TMyClass);
begin
  FMyArray[index].FName:= Value.FName;
  FMyArray[index].FValue:= Value.FValue;
end;

end.
MyArray1.parent:= MyComponent1;
MyArray2.parent:= MyComponent2;
...

。哪一个是更好的选择?或者还有其他更好的主意吗?

我会投票支持DefineProperties!必要的代码可能如下所示(假设数组中没有任何实例为nil):

最简单(也是首选)的解决方案是将
TMyClass
更改为派生自
TCollectionItem
,并将
TMyComponent.FMyArray
更改为
TOwnedCollection
。然后,DFM将为您自动流化项目,您将获得本地设计时支持,以创建和操作
TMyClass
对象及其属性

试试这个:

unit Unit1;

interface

uses
  Windows, ExtCtrls, Classes, Controls;

type
  TMyClass = class(TCollectionItem)
  private
    FName: string;
    FValue: double;

    procedure SetName(const AValue: string);
    procedure SetValue(AValue: double);
  public
    procedure Assign(ASource: TPersistent); override;
  published
    property Name: string read FName write SetName;
    property Value: double read FValue write SetValue;
  end;

  TMyArray = class(TOwnedCollection)
  private
    function  GetItem(Index: Integer): TMyClass;
    procedure SetItem(Index: Integer; const Value: TMyClass);
  public
    constructor Create(AOwner: TPersistent);
    function  Add: TMyClass; reintroduce;
    function  Insert(Index: Integer): TMyClass; reintroduce;
    property  Items[Index: Integer]: TMyClass read GetItem write SetItem; default;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyArray: TMyArray;

    procedure SetMyArray(Value: TMyArray);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property myArray: TMyArray read FMyArray write SetMyArray;
  end;

implementation

procedure TMyClass.Assign(ASource: TPersistent);
begin
  if ASource is TMyClass then
  begin
    with TMyClass(ASource) do
    begin
      Self.FName := Name;
      Self.FValue := Value;
    end;
    Changed(False);
  end else
    inherited;
end;

procedure TMyClass.SetName(const AValue: string);
begin
  if FName <> AValue then
  begin
    FName := AValue;
    Changed(False);
  end;
end;

procedure TMyClass.SetValue(AValue: double);
begin
  if FValue <> AValue then
  begin
    FValue := AValue;
    Changed(False);
  end;
end;

constructor TMyArray.Create(AOwner: TPersistent);
begin
  inherited Create(AOwner, TMyClass);
end;

function TMyArray.GetItem(Index: Integer): TMyClass;
begin
  Result := TMyClass(inherited GetItem(Index));
end;

procedure TMyArray.SetItem(Index: Integer; const Value: TMyClass);
begin
  inherited SetItem(Index, Value);
end;

function TMyArray.Add: TMyClass;
begin
  Result := TMyClass(inherited Add);
end;

function TMyArray.Insert(Index: Integer): TMyClass;
begin
  Result := TMyClass(inherited Insert(Index));
end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  FMyArray := TMyArray.Create(Self);
end;

destructor TMyComponent.Destroy;
begin
  FMyArray.Free;
  inherited;
end;

procedure TMyComponent.SetMyArray(Value: TMyArray);
begin
  FMyArray.Assign(Value);
end;

end.
单元1;
接口
使用
窗口、ExtCtrls、类、控件;
类型
TMyClass=类(TCollectionItem)
私有的
FName:字符串;
价值:双倍;
过程集合名(const AValue:string);
程序设定值(AValue:double);
公众的
程序分配(A来源:t持续);推翻
出版
属性名称:字符串读取FName写入SetName;
属性值:双读FValue写SetValue;
结束;
TMyArray=类别(TOwnedCollection)
私有的
函数GetItem(索引:整数):TMyClass;
过程SetItem(索引:整数;常量值:TMyClass);
公众的
构造函数创建(AOwner:TPersistent);
功能添加:TMyClass;重新引入;
函数插入(索引:整数):TMyClass;重新引入;
属性项[索引:整数]:TMyClass read GetItem write SetItem;违约
结束;
TMyComponent=class(TCustomPanel)
私有的
FMyArray:TMyArray;
过程SetMyArray(值:TMyArray);
公众的
构造函数创建(AOwner:TComponent);推翻
毁灭者毁灭;推翻
出版
属性myArray:TMyArray read FMyArray write SetMyArray;
结束;
实施
程序TMyClass.Assign(A来源:TPersistent);
开始
如果资源是TMyClass,那么
开始
使用TMyClass(ASource)do
开始
Self.FName:=名称;
Self.FValue:=值;
结束;
更改(假);
结束其他
继承;
结束;
过程TMyClass.SetName(const AValue:string);
开始
如果你是阿瓦鲁的话
开始
FName:=AValue;
更改(假);
结束;
结束;
程序TMyClass.SetValue(AValue:double);
开始
如果FValue AValue那么
开始
f值:=有效值;
更改(假);
结束;
结束;
构造函数TMyArray.Create(所有者:TPersistent);
开始
继承的Create(AOwner,TMyClass);
结束;
函数TMyArray.GetItem(索引:整数):TMyClass;
开始
结果:=TMyClass(继承的GetItem(索引));
结束;
过程TMyArray.SetItem(索引:整数;常量值:TMyClass);
开始
继承的集合项(索引、值);
结束;
函数TMyArray.Add:TMyClass;
开始
结果:=TMyClass(继承的Add);
结束;
函数TMyArray.Insert(索引:整数):TMyClass;
开始
结果:=TMyClass(继承的插入(索引));
结束;
构造函数TMyComponent.Create(所有者:TComponent);
开始
继承;
FMyArray:=TMyArray.Create(Self);
结束;
破坏器TMY组件。破坏;
开始
免费;
继承;
结束;
过程TMyComponent.SetMyArray(值:TMyArray);
开始
FMyArray.Assign(值);
结束;
结束。

我收到一个错误:[DCC错误]MyComponentTest1.pas(155):E2362无法访问受保护的symbol TReader.ReadProperty,WriteProperties也不能访问同样的内容!我忘了我在范围内有一个类助手来做这件事。更新了答案。仍然没有达到我的目标。。我将表单检查为文本,得到:
objectmycomponent1:tmycomponnent Left=160 Top=181 Width=185 Height=41 MyArray=(())
您是否将DefineProperties声明为override?找到了:TMyClass的属性必须发布才能与流媒体系统配合使用。我测试了这个版本,效果很好,我只需要在我的真实代码中进行测试,这有点复杂,感谢lotWas正在寻找同样的东西。雷米的回答很好,非常感谢。