属性没有被写入,只能从Delphi XE2中读取

时间:2014-10-12 18:18:03

标签: delphi properties call

我创建了自己的组件,里面有一个TFont 适当的属性。

该组件在公共声明

中具有以下属性
property CaptionFont: TFont read fCaptionFont write SetCaptionFont;

程序SetCaptionFont看起来像这样

procedure TMyComponent.SetCaptionFont(value: TFont);
begin
  fCaptionFont := value;
end;

我正在尝试使用以下代码将字体名称和字体大小分配给我的组件:

MyComponent.CaptionFont.Name := fGlobalStandardFontName;
MyComponent.CaptionFont.Size := fGlobalStandardFontSize;

但是,在行

处设置断点时
MyComponent.CaptionFont.Name := fGlobalStandardFontName;

然后点击" Trace Into(F7)"调试按钮,代码跳转到TFont代码和 完全忽略了SetCaptionFont过程。

我期待调用SetCaptionFont过程。

这里发生了什么?

2 个答案:

答案 0 :(得分:6)

将值分配给子属性时,不会调用

SetCaptionFont(),因为您没有为CaptionFont属性本身分配任何内容。

即使被调用,您的SetCaptionFont()也无法正确实施。您正在获取来源TFont的所有权并泄露原始TFont。您需要使用Assign()将源TFont值复制到现有的TFont

要检测子属性值更改(包括来自Assign()),您需要将OnChange事件处理程序分配给fCaptionFont对象,例如:

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  fCaptionFont := TFont.Create;
  fCaptionFont.OnChange := CaptionFontChanged;
end;

procedure TMyComponent.SetCaptionFont(value: TFont);
begin
  fCaptionFont.Assign(value);
end;

procedure TMyComponent.CaptionFontChanged(Sender: TObject);
begin
  Invalidate;
end;

procedure TMyComponent.Paint;
begin
  // use fCaptionFont as needed...
end;

答案 1 :(得分:1)

理解这一点的关键是赋值运算符的放置。

在属性上使用赋值运算符时,将调用属性设置器。使属性setter为您的属性执行的唯一方法是编写以下形式的代码:

CaptionFont := ...;

你不这样做。相反,你写:

CaptionFont.Name := ...;

此处使用CaptionFont的getter,然后使用Name的setter。

这解释了为什么不调用setter。

除此之外,你错误地实现了setter。您的实现可能会泄漏您在构造函数中创建的对象,该对象的引用位于FCaptionFont中。当您分配到FCaptionFont时,您将失去对该对象的跟踪。

属性属性的约定是将设置属性的操作转换为对Assign的调用。这使得属性具有值语义而不是引用。属性值被复制。因此,setter看起来像这样:

procedure TMyComponent.SetCaptionFont(Value: TFont);
begin
  FCaptionFont.Assign(Value);
end;