Lui*_*Jr. 2 delphi components properties class delphi-2009
如何设置组件对象属性值的默认值?
组件类代码:
unit CustomClass;
interface
uses
Classes;
type
TCustomClass = class;
TConfiguration = class;
TCustomClass = class (TComponent)
private
FConfiguration: TConfiguration;
procedure SetConfiguration(const Value: TConfiguration);
published
property Configuration: TConfiguration read FConfiguration write SetConfiguration;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TConfiguration = class (TPersistent)
private
FDelay: Integer;
FSize: Integer;
procedure SetDelay(const Value: Integer);
procedure SetSize(const Value: Integer);
published
property Delay: Integer read FDelay write SetDelay;
property Size: Integer read FSize write SetSize;
public
procedure Assign(Source: TPersistent); override;
end;
implementation
{ TCustomClass }
constructor TCustomClass.Create(AOwner: TComponent);
begin
inherited;
Configuration.FileName:= 'FileName';
Configuration.Size := 10;
end;
destructor TCustomClass.Destroy;
begin
Configuration.Free;
inherited;
end;
procedure TCustomClass.SetConfiguration(const Value: TConfiguration);
begin
FConfiguration.Assign(Value);
end;
{ TConfiguration }
procedure TConfiguration.Assign(Source: TPersistent);
begin
inherited;
Delay := (Source as TConfiguration).Delay;
Size := (Source as TConfiguration).Size;
end;
procedure TConfiguration.SetDelay(const Value: Integer);
begin
FDelay := Value;
end;
procedure TConfiguration.SetSize(const Value: Integer);
begin
FSize := Value;
end;
end.
Run Code Online (Sandbox Code Playgroud)
在我的IDE中,它将显示为对象属性被修改(粗体蓝色).
我想在TConfiguration类属性上创建默认和存储函数,如下所示:
TConfiguration
interface
private
function FileNameStored: Boolean;
published
property FileName: string read FFileName write SetFileName stored FileNameStored;
property Size: Integer read FSize write SetSize default 10;
implementation
function TConfiguration.FileNameStored: Boolean;
begin
Result := FileName <> 'FileName';
end;
Run Code Online (Sandbox Code Playgroud)
它以正常蓝色为TConfiguration的属性着色,但不是TCustomClass的Configuration属性,而不是我想要设置其默认值,在TCustomClass上,因为TConfiguration可能在另一个组件中使用.
然后,我还想:
TCustomClass
interface
private
function ConfigurationStored: Boolean;
published
property Configuration: TConfiguration read FConfiguration write SetConfiguration stored ConfigurationStored;
implementation
function TCustomClass.ConfigurationStored: Boolean;
begin
Result := Configuration.FileName <> 'FileName' and
Configuration.Size <> 10;
end;
Run Code Online (Sandbox Code Playgroud)
但是,这只将TCustomClass配置属性颜色设置为普通蓝色,而不是其属性.
回答
正如@RemyLebeau指出的那样(在第一个和最顶层的答案中),代码中存在错误.在该组件和那种情况下,我决定不为属性设置任何默认值.
您的代码中有几个错误.
你的TCustomClass构造函数没有创建TConfiguration对象.你需要添加:
constructor TCustomClass.Create(AOwner: TComponent);
begin
inherited;
FConfiguration := TConfiguration.Create; // <-- add this
FConfiguration.FileName := 'FileName';
FConfiguration.Size := 10;
end;
Run Code Online (Sandbox Code Playgroud)
话虽这么说,FileName和Size属性的赋值应该可以移动到TConfiguration构造函数而不是TCustomClass构造函数.
一个String属性不能用一个用户定义的默认值来定义,默认的始终是一个空字符串.因此,在FileName创建组件时,您的属性将始终显示为已修改,因为构造函数正在为其分配非默认值.你的stored方法是解决这个问题的正确方法.或者,只是不指定默认值FileName at all,将其留空.如果用户未指定显式FileName,则代码可以根据需要采用默认值.
的Integer属性,在另一方面,可以与用户定义的默认值来定义.但是,你的Size财产不是这样做的.它应该是(特别是如果您将默认值的赋值移动到TConfiguration构造函数中):
property Size: Integer read FSize write SetSize default 10;
Run Code Online (Sandbox Code Playgroud)您的TConfiguration.Assign()方法实现不正确.通过Assign()在复制值之前调用继承的方法,EConvertError如果调用者将一个TConfiguration对象分配给另一个对象,则代码将始终在运行时引发异常.原因是因为基类TPersistent.Assign()实现只是调用Source.AssignTo(Self),并且TConfiguration不会覆盖该AssignTo()方法,因此TPersistent.AssignTo()调用它,它只是调用Dest.AssignError(Self),从而引发异常.所以,Assign()如果Source它实际上是一个TConfiguration对象,请不要调用继承的方法:
procedure TConfiguration.Assign(Source: TPersistent);
begin
if Source is TConfiguration then
begin
FDelay := TConfiguration(Source).Delay;
FSize := TConfiguration(Source).Size;
end else
inherited;
end;
Run Code Online (Sandbox Code Playgroud)