Delphi和Lazarus在表单初始化方面的差异?

Delphi和Lazarus在表单初始化方面的差异?,delphi,freepascal,lazarus,Delphi,Freepascal,Lazarus,MainForm在运行时创建一些次框架对象以显示各种选项面板 下面是其中一个框架类的典型构造函数(它们都扩展了TFrame): 这段代码在Delphi中运行良好(无论它是否是正确的操作方式),但Lazarus中的同一段代码一直抛出EINValidoOperation异常,因为控件(TEdit)尚未分配父“窗口”(rsControlHasNoParentWindow),当我检查代码时,这实际上是有意义的,因为在调用构造函数之前,父级似乎不会被赋值 以下是初始化次帧的主窗体中的代码: if Assi

MainForm在运行时创建一些次框架对象以显示各种选项面板

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

这段代码在Delphi中运行良好(无论它是否是正确的操作方式),但Lazarus中的同一段代码一直抛出EINValidoOperation异常,因为控件(TEdit)尚未分配父“窗口”(rsControlHasNoParentWindow),当我检查代码时,这实际上是有意义的,因为在调用构造函数之前,父级似乎不会被赋值

以下是初始化次帧的主窗体中的代码:

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在表单初始化顺序方面是否有重要的区别吗

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


编辑]:看起来这可能在某种程度上特定于TEdit。似乎初始化复选框状态的行没有相同的问题。这可能只是Lazarus中的一个bug吗?

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

edTime.Parent := Self;
edTime.Text := '12:00';
但我仍然想更好地理解为什么“有时”需要这样做

编辑:虽然这修复了在TEdit上设置文本的问题,但并没有修复我的自动大小调整代码,该代码会遍历组件并调整任何复选框的大小。显然,没有父集合的表单仍然是一个“有点”的问题


edit2:在构造函数中添加第二个参数,并在构造函数中为整个表单设置父级,似乎消除了为TEdit设置父级的需要。我不知道这是否解决了问题,但设置继承的Create(AOwner);在创建过程中。尝试简单的代码TEdit.create(nil)。文本:='12345';此代码创建无父编辑并为其指定一些标题。如果这在VCL中起作用,但在LCL中不起作用,那么这恰恰意味着它们是有父项的不同wrt。还请注意,LCL只是针对某些工具箱库的包装器。GTK+上有LCL,Qt上有LCL,谁知道还有什么。也许您可以将LCL后端切换到另一个库并修复它。也许不是。我试过了,但我无法复制这个问题(lazarus 0.9.30.4)。我尝试在一个新的从头开始的应用程序上重新创建错误,但也无法像从delphi导入的项目中那样在那里发生错误。我猜很可能我从Delphi导入的项目中的项目设置或编译器选项必须不同。这几乎总是在创建可视化控件(如
TEdit
)时需要的。它有可视内容,所以它需要在某个地方绘制该内容,这是在
Parent.Canvas
上。DFM流方法会自动执行此操作(您可以在结构视图中查看子控件的
沿袭
父顺序
,或者通过将DFM视为文本并观察缩进级别来查看)。当您在运行时在代码中创建控件时,您必须自己创建(正如您所发现的)。
edTime.Parent := Self;
edTime.Text := '12:00';