设计时属性的值,不会出现在运行时
Posted
技术标签:
【中文标题】设计时属性的值,不会出现在运行时【英文标题】:Values of a property at design time, doesn't appear at run time 【发布时间】:2013-05-22 15:31:56 【问题描述】:我有以下组件,其中包含从自定义类派生的属性:
unit MyComponentTest3;
interface
uses Windows, ExtCtrls,Classes,Controls;
type
TMyClass3 = class
myString: string;
myNumber: double;
end;
TMyComponentTest3 = class(TCustomPanel)
private
FMyProperty: TMyClass3;
procedure SetMyProperty(Value: TMyClass3);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetMyPropertyPublic(AmyString: string; AmyNumber: double);
published
property MyProperty: TMyClass3 read FMyProperty write SetMyProperty;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MyComponents', [TMyComponentTest3]);
end;
TMyComponentTest3
constructor TMyComponentTest3.Create(AOwner: TComponent);
begin
inherited;
FMyProperty:= TMyClass3.Create;
end;
destructor TMyComponentTest3.Destroy;
begin
FMyProperty.Free;
inherited;
end;
procedure TMyComponentTest3.SetMyProperty(Value: TMyClass3);
begin
with FMyProperty do
begin
myString:= Value.myString;
myNumber:= Value.myNumber;
end;
end;
procedure TMyComponentTest3.SetMyPropertyPublic(AmyString: string;
AmyNumber: double);
var
auxMyProperty: TMyClass3;
begin
auxMyProperty:= TMyClass3.Create;
with auxMyProperty do
begin
myString:= AmyString;
myNumber:= AmyNumber;
end;
SetMyProperty(auxMyProperty);
auxMyProperty.Free;
end;
end.
它工作正常,但是当我在设计时设置属性的值并运行程序时,值消失了。如果我设置组件的值,保存所有内容,当我加载这些值时,我会遇到同样的问题......
我想问题是因为我一直在创建自定义类的实例,但我不确定,也不知道如何解决这个问题。有人知道我能做什么吗?
【问题讨论】:
有什么理由不让TMyClass3
成为记录而不是类?
这只是一个简单的例子,在我的真实代码中它更复杂......
@J... 不管它有多复杂,关键的决定因素是你想要值还是引用赋值语义。
【参考方案1】:
TMyClass3
需要派生自 TPersistent
才能在 DFM 中进行流式传输。它还应该选择性地覆盖虚拟的Assign()
方法,然后SetMyProperty()
将能够调用该方法。
试试这个:
unit MyComponentTest3;
interface
uses
Windows, ExtCtrls, Classes, Controls;
type
TMyClass3 = class(TPersistent)
private
FMyString: string;
FMyNumber: double;
public
procedure Assign(Source: TPersistent); override;
published
property myString: string read FMyString write FMyString;
property myNumber: double read FMyNumber write FMyNumber;
end;
TMyComponentTest3 = class(TCustomPanel)
private
FMyProperty: TMyClass3;
procedure SetMyProperty(Value: TMyClass3);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetMyPropertyPublic(AmyString: string; AmyNumber: double);
published
property MyProperty: TMyClass3 read FMyProperty write SetMyProperty;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MyComponents', [TMyComponentTest3]);
end;
TMyClass3
procedure TMyClass3.Assign(Source: TPersistent);
begin
if Source is TMyClass3 then
begin
with TMyClass3(Source) do
begin
Self.FMyString := myString;
Self.FMyNumber := myNumber;
end;
end else
inherited;
end;
TMyComponentTest3
constructor TMyComponentTest3.Create(AOwner: TComponent);
begin
inherited;
FMyProperty := TMyClass3.Create;
end;
destructor TMyComponentTest3.Destroy;
begin
FMyProperty.Free;
inherited;
end;
procedure TMyComponentTest3.SetMyProperty(Value: TMyClass3);
begin
FMyProperty.Assign(Value);
end;
procedure TMyComponentTest3.SetMyPropertyPublic(AmyString: string; AmyNumber: double);
begin
with MyProperty do
begin
myString := AmyString;
myNumber := AmyNumber;
end;
end;
end.
【讨论】:
没什么...它似乎没有到达这个分配过程,值仍然没有出现在运行时,我在分配过程中放了一条消息来检查它从来没有显示它Assign()
不会被调用,因为在 DFM 流式传输期间不会调用属性设置器。这个建议只是为了清理你的设置器并实现更好的封装。您的问题是另外一回事,但您仍然需要从基础开始 - 从TPersistent
派生,使子值本身成为已发布的属性等。您所描述的表明这些值并没有被保存到 DFM 开始,因此不存在以供稍后加载。
在设计时测试组件的 DFM 流功能的一种简单方法是将组件拖放到表单上,根据需要设置属性,右键单击表单设计器并选择“以文本形式查看”并验证值是否存在,然后再次右键单击并选择“以表单查看”并验证值是否在组件中。如果您的值没有按预期工作,那么某些东西就坏了。
只有发布的属性会和组件一起保存?我有一个属性,它是一个数组,我不能发布它,但是我需要保存它的值......你知道怎么做吗?
是的,默认情况下,只有使用支持的数据类型的 published
属性会被流式传输。要流式传输其他数据,您需要覆盖虚拟DefineProperties()
方法以提供自定义流式传输。【参考方案2】:
constructor TMyComponentTest3.Create(AOwner: TComponent);
begin
inherited;
FMyProperty := TMyClass3.Create;
FMyProperty.SetSubComponent(True);
end;
【讨论】:
以上是关于设计时属性的值,不会出现在运行时的主要内容,如果未能解决你的问题,请参考以下文章
DirectX 11:运行简单的 DirectX 应用程序时运行时崩溃
为啥 Kubernetes 的容器在 runsc (gVisor) 上作为 Docker 中的运行时运行时会失败?