Float属性非零默认值,可以吗?

问题描述 投票:4回答:5

我想在组件中使用float属性,但将其设置为一些非零的默认值(假设它是1000.0)。如果我尝试在Create中执行此操作,则该属性开始表现异常,因为默认值将其浮动为0(请参见classes.TWriter.WriteProperty.WriteFloatProp.IsDefaultValue),因此当我在表单设计人员,delphi不会保存该值(在这种情况下为默认值),但是当下次加载组件时,我的Create会将其设置为1000.0,因此实际上我具有我未设置的值。

问题是无法用'default'指令设置默认值(编译器说'默认值必须是序数,指针或小集合类型'),并且也无法强制使用存储的指令,它不起作用(Delphi 5)

所以有机会找到解决方法吗?

谢谢,

最大

delphi properties floating-point components
5个回答
1
投票

也许您可以使用stored指令:

property MyFloat: Float read GetValue write SetValue stored IsMyFloatStored;

具有返回True且MyFloat的布尔函数IsMyFloatStored没有其默认值。


1
投票

我通过在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进行破解)。为了使其线程安全(并且因为TFiler.DefineProperty需要“对象”功能),我将整个对象封装在一个对象中。

就我而言,我希望默认值为uiFloat。该常数可以设置为您想要的任何值。如果要为不同的属性使用不同的默认值,则可以轻松地将默认值作为参数添加到“创建”函数中。

请注意,您仍然必须将属性设置为TMyObj的构造函数中的默认值。

在我看来,这是解决Delphi中相当严重的限制的一种非常有效的方法。

编辑:您需要记住要在所有使用此属性的属性中添加“ false”。


0
投票

如编译器所说,浮点值不能具有默认值。我唯一能想到的就是将浮点值存储在标度整数中。例如,如果只需要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。但是该属性将是一个可缩放的整数,因此可以很好地存储。


0
投票

默认值实际上仅告诉流代码默认值是什么,如果是默认值,则不进行流传输。这省去了流式传输所有默认值的麻烦。无论如何,该组件实际上必须在.Create中设置默认值。编译器没有任何魔力为您设置默认值。

在这种情况下,没有关系,因为您可以在.Create构造函数中设置默认值,然后在定义中保留默认值。该值将始终存储,但是将根据需要运行。


0
投票

只是遇到了这个问题,并通过在构造函数中将我想要的值设置为默认值并对该属性使用nodefault指令来解决了该问题。

© www.soinside.com 2019 - 2024. All rights reserved.