【问题标题】:How do I code a property with sub-properties? (redux)如何使用子属性对属性进行编码? (还原)
【发布时间】:2010-09-28 07:36:24
【问题描述】:

我确信我在my previous question 上得到了很好的回答,因为我之前从那里发帖的人那里得到了很多其他问题的帮助。

但我显然做错了,因为当我复制示例代码时,对象检查器向我显示的 MyProp 属性是单个文本输入字段。我期待看到类似于 Font 属性的内容,包括 Pitch、字体系列等,即我希望看到树结构,但我没有看到 MyProp 属性的 Color、Height 或 Width 属性。

有什么想法吗?同样,我完全复制了该代码。


编辑:我忘了提到(在这个问题中)我正在使用 TMS scripter pro,它允许用户在运行时设计表单并提供自己的对象检查器,但这可能源自标准的 Delphi 东西,我猜.

无论如何,我似乎太笨了,无法编写 Delphi 代码,因为我根本无法让它工作。


编辑:TMS 向我保证,如果具有“子属性”的类是 TPresistent 的后代,那么它将出现在具有子属性的对象检查器中,就像字体、锚点等一样

当我使用此代码时,“警告”属性在对象检查器中显示为文本字段并且没有子属性

unit IntegerEditBox;
  // An edit box which only accepts integer values and warns if the value is not in a certain range

interface

uses
  SysUtils, Classes, Controls, StdCtrls,
  EditBox_BaseClass;

type

  TWarning = Class(TPersistent)
    private
      FWarningBelowValue   : Integer;
      FWarningAboveValue   : Integer;
      FWarningEmailTo : String;
      FWarningSmsTo   : String;
    published
      property WarningBelowValue   : Integer read FWarningBelowValue   write FWarningBelowValue;
      property WarningAboveValue   : Integer read FWarningAboveValue   write FWarningAboveValue;
      property WarningEmailTo      : String  read FWarningEmailTo      write FWarningEmailTo;
      property WarningSmsTo        : string  read FWarningSmsTo        write FWarningSmsTo;
  end;


  TIntegerEditBox = class(TEditBox_BaseClass)
    private
      FWarning : TWarning;
      procedure WriteValue(const newValue : Integer);


    protected
      // The new property which w/e introduce in this class
      FValue : Integer;   

    public { Public declarations }
      Constructor Create(AOwner: TComponent); override;   // This constructor uses defaults
      property Text;

    published  { Published declarations - available in the Object Inspector at design-time }
      property Hint;

      // Now our own properties, which we are adding in this class
      property Value : Integer read FValue write WriteValue;
      property Warning  : TWarning read FWarning write FWarning ;
  end;  // of class TIntegerEditBox()

procedure Register;

implementation

uses
  Dialogs;

  procedure Register;
  begin
    RegisterComponents('Standard', [TIntegerEditBox]);
  end;

  Constructor TIntegerEditBox.Create(AOwner: TComponent);
  begin
    inherited;  // Call the parent Create method
    Hint := 'Only accepts a number|Only accepts a number'; // Tooltip | status bar text
    Mandatory := True;
    Value := 0;
    Text := IntToStr(Value);
  end;

  procedure TIntegerEditBox.WriteValue(const newValue : Integer);
  begin
    Text := IntToStr(newValue);
  end;

end.

【问题讨论】:

  • 您接受的答案中的代码至少有一个问题 - 有关详细信息,请参阅 Remy Lebeau 对已接受答案的评论。
  • 其他讨论中的“已接受答案”代码仅显示声明,没有显示任何实际实现代码,因此您很可能错过了重要步骤。我已经编辑了早期的代码以显示现在的实现。
  • +1 我完全同意。那是我非常糟糕的形式。我唯一的借口是我出差了,这让我无法尝试它,而且添加了几个 cmets 的 @RRUZ @Remy 从来没有误导我——看看他们的代表。不幸的是,SO几乎迫使你接受一些东西,只是任何东西;没有选择说“我没有得到满意的答案”,所以有时我只是把它交给最努力的人。还能做什么?
  • @Mawg:您可以选择在没有接受答案的情况下暂时离开问题。直到现在我发布的唯一问题就是这种情况,我得到了 1 个非常好的答案,但它并不完美,并且尚未标记为已接受。我想得到正确的,我愿意合作以达到正确。
  • 这个问题询问上一个问题的代码有什么问题。上一个问题有一个公认的答案,表明它现在没有任何问题。对于this问题,您希望得到什么进一步的答案?

标签: delphi


【解决方案1】:

the demo codeoriginal version 忽略了创建属性对象的实例。

constructor TMyControl.Create(AOwner: TComponent)
begin
  inherited;
  FMyProp := TCustomType.Create;
end;

别忘了在析构函数中释放它。

Remy 对该答案的评论指出需要以不同方式分配属性。该属性的 write 访问器不应直接写入该字段。相反,它应该有一个像这样工作的 setter 方法:

procedure TMyControl.SetMyProp(const Value: TCustomType);
begin
  FMyProp.Assign(Value);
end;

这也强调了实现属性类的Assign 方法的要求,否则您会收到奇怪的错误消息,例如“无法将 TCustomType 分配给 TCustomType”。一个简单的实现可以是这样的:

procedure TCustomType.Assign(Source: TPersistent);
begin
  if Source is TCustomType then begin
    Color := TCustomType(Source).Color;
    Height := TCustomType(Source).Height;
    Width := TCustomType(Source).Width;
  end else
    inherited;
end;

【讨论】:

  • 这些细节已经添加到其他讨论的代码中了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多