Delphi 从自定义类派生的组件属性

Delphi 从自定义类派生的组件属性,delphi,class,components,Delphi,Class,Components,我创建了我自己的类,我想在我的新组件中使用它,但我得到了一个错误。。。 代码如下: type TMyClass = class Name: string; Number: double; end; TMyComponent = class(TCustomPanel) private FMyClass: TMyClass; public procedure SetMyClass(aName: string; aNumber: double);

我创建了我自己的类,我想在我的新组件中使用它,但我得到了一个错误。。。 代码如下:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
  public
    procedure SetMyClass(aName: string; aNumber: double);
  published
    property MyClass: TMyClass write SetMyClass;
  end;

procedure SetMyClass(aName: string; aNumber: double);
begin
  FMyClass.Name:= aName;
  FMyClass.Number:= aNumber;
end;
该属性似乎有不兼容的类型,我不知道为什么

有人对此有线索吗?我该如何解决这个问题。 在TMyComponent中使用FName和FNumber作为字段不是一个选项,我的代码更复杂,这是一个简单的例子来解释我的目标

谢谢

试试这个:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
  public
    procedure SetMyClass(Value: TMyClass);
  published
    property MyClass: TMyClass write SetMyClass;
  end;

procedure TMyComponent.SetMyClass(Value);
begin
  FMyClass := Value;
end;

目前,我发现您的代码存在以下错误:

  • 属性设置程序必须接收与属性类型相同的单个参数,即
    TMyClass
  • 属性设置器必须是该类的成员,但您已经将其作为独立过程实现
  • 已发布的属性需要有一个getter
  • 因此,代码将变成:

    type
      TMyClass = class
        Name: string;
        Number: double;
      end;
    
      TMyComponent = class(TCustomPanel)
      private
        FMyClass: TMyClass;
        procedure SetMyClass(Value: TMyClass);
      published
        property MyClass: TMyClass read FMyClass write SetMyClass;
      end;
    
    procedure TMyComponent.SetMyClass(Value: TMyClass);
    begin
      FMyClass.Name:= Value.Name;
      FMyClass.Number:= Value.Number;
    end;
    
    此代码不实例化
    FMyClass
    。我猜实例化
    FMyClass
    的代码是为了这个问题而被删除的更大组件代码的一部分。但显然,您确实需要实例化
    FMyClass

    实例化
    FMyClass
    的另一种方法是将
    TMyClass
    转换为记录。我不知道那是否适合你的需要


    您在实例化此对象时似乎遇到了一些问题。这样做:

    type
      TMyClass = class
        Name: string;
        Number: double;
      end;
    
      TMyComponent = class(TCustomPanel)
      private
        FMyClass: TMyClass;
        procedure SetMyClass(Value: TMyClass);
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property MyClass: TMyClass read FMyClass write SetMyClass;
      end;
    
    constructor TMyComponent.Create(AOwner: TComponent);
    begin
      inherited;
      FMyClass:= TMyClass.Create;
    end;
    
    destructor TMyComponent.Destroy;
    begin
      FMyClass.Free;
      inherited;
    end;
    
    procedure TMyComponent.SetMyClass(Value: TMyClass);
    begin
      FMyClass.Name:= Value.Name;
      FMyClass.Number:= Value.Number;
    end;
    

    最后一点意见。对对象使用
    MyClass
    是个坏名字。对类型使用类,对实例使用对象。因此,您的属性应该是
    MyObject
    ,成员字段应该是
    fmyoobject
    等等。

    我相信Felipe的代码不完整,我假设不存在什么。此外,不存在GET函数,因此不存在风险读取。您已经接受了这一点,但这不太可能是您的答案。你会从左右和中间漏出物体。我试图说服大卫讨论那个问题,但到目前为止他还没有同意。同样奇怪的是,您在问题中的代码将
    MyClass
    视为一个值,但您接受的答案在没有解释的情况下将语义更改为
    reference
    。感谢您提供的信息,我现在明白了我的错误所在。但是我仍然遇到一个问题,我现在可以编译并安装它,但是当我在表单上删除组件时,我得到了“地址00000000处的访问冲突。读取地址00000000”。并且该组件不会出现在表单上。你知道原因吗?记住你没有给我们看你的代码。您只显示了代码的精简版本。我的答案中的代码仍然被删掉了,由你来引导。请注意我对
    FMyClass
    未实例化这一事实的讨论。我们只能对您向我们展示的代码进行评论。你有没有实例化过
    FMyClass
    ?我在这里发布了一个我自己的代码示例,在这个简单的示例中,我也得到了你的代码必须调用继承的相同错误;作为构造函数的第一行。不要忘记
    TMyClass
    也必须从
    TPersistent
    派生,以便DFM可流化,因为它被声明为
    已发布
    。这意味着什么?这正是我已经说过的。因为没有析构函数,所以你还在泄漏。你需要关于构造函数和析构函数的帮助吗?另一个问题是你缺少对继承构造函数的调用,你说我应该实例化FMyClass,所以它就在那里:FMyClass:=TMyClass.Create;如果不是这样的话,我不知道如何正确实例化这个类,这一点很好。但是create中丢失的析构函数和继承的丢失仍然在伤害你。是的,我已经纠正了这一点,我忘记了,因为我写这段代码很快就向你展示了,但是即使仍然存在内存泄漏。。。
    unit MyComponentTest2;
    
    interface
    
    uses SysUtils, Classes, Controls, Forms, ExtCtrls, Messages, Dialogs;
    
    type
      TMyClass = class
        Name: string;
        Number: double;
      end;
    
      TMyComponentTest2 = class(TCustomPanel)
      private
        FMyClass: TMyClass;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
    
        procedure SetMyClass(Value: TMyClass);
      published
        property MyClass: TMyClass read FMyClass write SetMyClass;
      end;
    
    procedure Register;
    
    implementation
    
    constructor TMyComponentTest2.Create(AOwner: TComponent);
    begin
      Inherited Create(AOwner);
      FMyClass:= TMyClass.Create;
    end;
    
    destructor TMyComponentTest2.Destroy;
    begin
      Inherited;
      FMyClass.Free;
    end;
    
    procedure TMyComponentTest2.SetMyClass(Value: TMyClass);
    begin
      FMyClass.Name:= Value.Name;
      FMyClass.Number:= Value.Number;
    end;
    
    procedure Register;
    begin
      RegisterComponents('MyComponents', [TMyComponentTest2]);
    end;
    
    end.