【问题标题】:Differences in Form Initialization between Delphi and Lazarus?Delphi和Lazarus在表单初始化上的区别?
【发布时间】:2012-09-17 15:38:22
【问题描述】:

MainForm 在运行时创建一些辅助 Frame 对象来显示各种选项面板。

这是其中一个框架类的典型构造函数(它们每个都扩展 TFrame):

constructor Tframe2.Create(AOwner: TComponent);
begin
    inherited;
    edTime.Text := '12:00pm'; //edTime is a TEdit control. this line is where it throws the exception
    //etc.
end;

这段代码在 Delphi 中运行良好(无论它是否是正确的做事方式),但 Lazarus 中的相同代码不断抛出 EInvalidOperation 异常,因为控件(TEdit)尚未分配父“窗口”( rsControlHasNoParentWindow),当我检查代码时这实际上是有道理的,因为直到调用构造函数之后父级似乎才被分配。

这是 MainForm 中初始化辅助框架的代码:

if Assigned(frame) then FreeAndNil(frame);
case Node.AbsoluteIndex of
    optInterval: frame := Tframe2.Create(Self); //here's where the constructor gets called.
    //etc
end;
frame := TframeOther.Create(Self); 
if Assigned(frame) then
begin
    frame.Parent := panOptions; //here's where Tframe2's parent gets set
    frame.Align := alClient;
end;  

那么,就表单初始化顺序而言,任何人都可以解释 Delphi 和 Lazarus 之间是否存在任何重要差异?

解决此类初始化顺序问题的最标准方法是什么?与我更熟悉的其他语言相比,可能有不同的策略来解决此类错误。我可以向构造函数添加另一个参数,或者如果有一个方法被称为构造函数后在屏幕上预绘制它,我可以覆盖我可以重新定位该代码,或者只是创建一个辅助方法并在 setParent 被调用后调用它。这里有什么特别的最佳实践吗?

Edit]:看起来这可能以某种方式特定于 TEdit。看起来初始化复选框状态的行没有同样的问题。这可能只是 Lazarus 中的一个错误吗?

【问题讨论】:

  • 我不知道这是否能解决问题,但设置继承的 Create(AOwner);在创建过程中。
  • 试试简单的代码 TEdit.Create(nil).Text := '12345';此代码创建无父编辑并为其分配一些标题。如果这在 VCL 中有效,但在 LCL 中无效 - 那么这正是意味着它们与父级不同。另请注意,LCL 只是针对某些工具包库的包装器。有 GTK+ 上的 LCL,Qt 上的 LCL,还有谁知道还有什么。也许您可以将 LCL 后端切换到另一个库并修复它。也可能不是。
  • 我试了一下,但我无法复制这个问题(lazarus 0.9.30.4)。
  • 我尝试在一个新的从头开始的应用程序上重新创建错误,但也无法像从 delphi 项目中导入的那样在那里发生错误。我猜很可能是我从 Delphi 导入的项目中的项目设置或编译器选项必须不同。

标签: delphi freepascal lazarus


【解决方案1】:

经过进一步的实验,我已经能够通过添加一行将 TEdit 的父级设置为 Frame(而不是设置 Frame 的父级)来解决它崩溃的大部分直接问题。像这样:

edTime.Parent := Self;
edTime.Text := '12:00';

但我仍然希望更好地了解为什么这是“有时”需要的。

edit:虽然这修复了能够在 TEdit 上设置文本的问题,但这并不能修复我拥有的自动调整大小的代码,它遍历组件并调整任何碰巧是复选框的大小。显然,没有父集的表单仍然是“某种”问题。

edit2:向构造函数添加第二个参数并在构造函数中为整个表单设置父级似乎完全不需要为 TEdit 设置父级。

【讨论】:

  • 当你创建一个可视化控件时几乎总是需要这个(比如TEdit)。它有视觉内容,所以它需要在某个地方来绘制该内容,那就是Parent.Canvas。 DFM 流式处理方法会自动执行此操作(您可以在结构视图中看到子控件的 lineageparent order,或者将 DFM 作为文本查看并观察缩进级别)。当您在运行时在代码中创建控件时,您必须自己完成(正如您所发现的那样)。
猜你喜欢
  • 2018-10-29
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2010-11-06
相关资源
最近更新 更多