浮点属性非零默认值,有可能吗?
Posted
技术标签:
【中文标题】浮点属性非零默认值,有可能吗?【英文标题】:Float property non-zero default, is it possible? 【发布时间】:2011-04-28 01:56:03 【问题描述】:我想在我的组件中使用浮点属性,但将其设置为某个非零默认值(假设它是 1000.0)。如果我尝试在 Create 中执行此操作,则该属性开始表现得很疯狂,因为它的默认值浮动为 0(请参阅 classes.TWriter.WriteProperty.WriteFloatProp.IsDefaultValue)所以当我用0 在表单设计器中,delphi 不保存这个值(在这种情况下是默认值),但是我的 Create 会在下次加载组件时将它设置为 1000.0,所以实际上我有我没有的值放。
问题是没有办法用'default'指令设置默认值(编译器说'默认值必须是序数,指针或小集合类型'),这也是不可能的强制使用存储指令进行存储,它不起作用(Delphi 5)
那么有机会找到解决方法吗?
谢谢,
最大
【问题讨论】:
我对这个问题的解决方案也很感兴趣。你有想过解决办法吗? 【参考方案1】:也许你可以使用stored
指令:
property MyFloat: Float read GetValue write SetValue stored IsMyFloatStored;
如果 MyFloat 没有其默认值,则返回 True 的布尔函数 IsMyFloatStored
。
【讨论】:
Ulrich,我希望它会有所帮助,但看起来存储过滤器在默认值处理之前工作,因此它不能用于覆盖默认比较处理【参考方案2】:我通过在我的 TPersistent 后代中实现 DefineProperties 方法解决了这个问题。我想为这个问题制定一个通用的解决方案,我可以轻松地在我的所有对象中为所有相关属性实现它。下面是它的外观:
TOverridePropFiler = class
private
FReadWritePropName: string;
FObject: TObject;
procedure ReadOverrideProp(Reader: TReader);
procedure WriteOverrideProp(Writer: TWriter);
public
constructor Create(Filer:TFiler; Obj:TObject; Name:string);
end;
TOverridePropFiler
constructor TOverridePropFiler.Create(Filer:TFiler; Obj:TObject; Name:string);
begin
FReadWritePropName:=Name;
FObject:=obj;
if (Name='') or not Assigned(GetPropInfo(Obj,Name)) then
Raise Exception.CreateFmt('Property %s not found in object %s',[Name,Obj.ClassName]);
Filer.DefineProperty(Name, ReadOverrideProp, WriteOverrideProp,
GetPropValue(FObject,FReadWritePropName,False)<>uiFloat);
end;
procedure TOverridePropFiler.ReadOverrideProp(Reader: TReader);
begin
SetPropValue(FObject,FReadWritePropName,Reader.ReadFloat);
end;
procedure TOverridePropFiler.WriteOverrideProp(Writer: TWriter);
begin
Writer.WriteDouble(GetPropValue(FObject,FReadWritePropName,False));
end;
我在我的 DefineProperties 方法中调用它如下:
procedure TMyObj.DefineProperties(Filer: TFiler);
begin
inherited;
TOverridePropFiler.Create(Filer,Self,'dTOverride').Free;
end;
为了使这个通用化,我必须使用 RTTI 并在本地保存属性名称(不可能从 TWriter 中得到它,并且需要对 TReader 进行 hack)。为了使其线程安全(并且因为 TFiler.DefineProperty 需要“对象”函数),我将整个东西封装在一个对象中。
就我而言,我希望默认值为 uiFloat。这个常数可以设置为任何你想要的。如果您想为不同的属性设置不同的默认值,您可以轻松地将默认值作为参数添加到 Create 函数中。
请注意,您仍然需要在 TMyObj 的构造函数中将属性设置为默认值。
在我看来,这是解决 Delphi 中一个相当严重的限制的一种相当有效的方法。
编辑:您需要记住将“stored false”添加到所有使用它的属性。
【讨论】:
【参考方案3】:刚刚遇到这个问题,并通过在构造函数中将我想要的值设置为默认值并对该属性使用 nodefault 指令来解决它。
【讨论】:
【参考方案4】:正如编译器所说,浮点值不能有默认值。我唯一能想到的是将浮点值存储在一个缩放的整数中。例如,如果您只需要三位小数的yourFloat
,则可以改为存储yourInt = 1000 * yourFloat
。然后默认值为yourInt := 1000000
,对应于yourFloat := 1000.000
。
当然,你可以做得更优雅一点,比如
private
FMyFloat: real;
function GetValue: integer;
procedure SetValue(Value: integer);
published
property MyInteger: integer read GetValue write SetValue default 1000000;
implementation
function TMyClass.GetValue: integer;
begin
result := round(1000 * FMyFloat);
end;
procedure TMyClass.SetValue(Value: integer);
begin
FMyFloat := Value / 1000;
end;
这样,您仍然只能从类本身内部看到浮点字段 FMyFloat
。但该属性将是一个缩放整数,因此可以完美存储。
【讨论】:
谢谢,但不幸的是它在设计器中应该表现得像浮动。只是认为字符串属性(只接受格式正确的浮点数)可能是另一种选择【参考方案5】:默认值实际上只是告诉流代码默认值是什么,如果是那个值,那么它就不会被流式传输。这样就不必流式传输所有默认值。组件实际上必须在 .Create 中设置默认值。编译器不会为您设置默认值。
在这种情况下,这无关紧要,因为您可以在 .Create 构造函数中设置默认值,然后在定义中省略默认值。该值将始终被存储,但它会按照您的意愿工作。
【讨论】:
不,VCL 的实际代码违背了我的意图。看,如果您将浮点值更改为 0,则该值将不会被流式传输。在这种情况下,我在 Create 中设置的属性没有被覆盖。换句话说,我的手(当我按下 Enter 键时)想要将某个值更改为零,但是当表单加载时,它将返回到我的非零默认值(因为没有流式传输)。以上是关于浮点属性非零默认值,有可能吗?的主要内容,如果未能解决你的问题,请参考以下文章