【问题标题】:Array of a custom class as a property自定义类的数组作为属性
【发布时间】:2013-05-25 00:41:21
【问题描述】:

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

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.

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

TMyClass=class(T???????????)

这样我就可以取出属性 MyArray 并创建 TMyClass 并添加到 TMyComponent 中,如下所示:

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

。哪一个是更好的选择?或者还有什么更好的办法吗?

【问题讨论】:

    标签: class delphi components


    【解决方案1】:

    最简单(也是首选)的解决方案是将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.
    

    【讨论】:

    • 我测试了这个版本,它工作正常,我只需要在我的真实代码中测试,这有点复杂,非常感谢
    • 正在寻找同样的东西。雷米的回答很好,非常感谢。
    【解决方案2】:

    我会投票给 DefineProperties!必要的代码可能如下所示(假设数组中没有一个实例是 nil):

    procedure TMyComponent.DefineProperties(Filer: TFiler);
    begin
      inherited;
      Filer.DefineProperty('MyArray', ReadMyArray, WriteMyArray, true);
    end;
    
    procedure TMyComponent.ReadMyArray(Reader: TReader);
    var
      N: Integer;
    begin
      N := 0;
      Reader.ReadListBegin;
      while not Reader.EndOfList do begin
        Reader.ReadListBegin;
        FMyArray[N].Name := Reader.ReadString;
        FMyArray[N].Value := Reader.ReadFloat;
        Reader.ReadListEnd;
        Inc(N);
      end;
      Reader.ReadListEnd;
    end;
    
    procedure TMyComponent.WriteMyArray(Writer: TWriter);
    var
      I: Integer;
    begin
      Writer.WriteListBegin;
      for I := 0 to High(FMyArray) do begin
        Writer.WriteListBegin;
        Writer.WriteString(FMyArray[I].Name);
        Writer.WriteFloat(FMyArray[I].Value);
        Writer.WriteListEnd;
      end;
      Writer.WriteListEnd;
    end;
    

    【讨论】:

    • 我得到一个错误:[DCC Error] MyComponentTest1.pas(155): E2362 Cannot access protected symbol TReader.ReadProperty 和 WriteProperties 一样
    • 确实!我忘记了我在范围内有一个班级助手可以做这件事。更新了答案。
    • 仍然没有达到我的目标..我将表单作为文本检查,我得到了:object MyComponent1: TMyComponent Left = 160 Top = 181 Width = 185 Height = 41 MyArray = ( ())
    • 您是否将 DefineProperties 声明为覆盖?
    • 找到了:必须发布 TMyClass 的属性才能与流系统一起使用。
    猜你喜欢
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2011-01-14
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    相关资源
    最近更新 更多