Delphi和Lazarus之间表单初始化的差异?

Jes*_*own 6 delphi freepascal lazarus

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;
Run Code Online (Sandbox Code Playgroud)

这段代码在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;  
Run Code Online (Sandbox Code Playgroud)

那么有人可以解释Delphi和Lazarus之间在表单初始化序列方面是否存在任何重要差异?

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

编辑]:看来这可能是某种特定的TEdit.看起来初始化复选框状态的行没有相同的问题.这可能只是拉撒路的一个错误吗?

Jes*_*own 1

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

edTime.Parent := Self;
edTime.Text := '12:00';
Run Code Online (Sandbox Code Playgroud)

但我仍然想更好地理解为什么“有时”需要这样做。

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

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

  • 当您创建可视控件(如“TEdit”)时,这几乎总是需要的。它具有视觉内容,因此需要在某个地方绘制该内容,那就是“Parent.Canvas”。DFM 流方法会自动执行此操作(您可以在结构视图中查看子控件的“沿袭”或“父顺序”,或者通过将 DFM 作为文本查看并观察缩进级别来查看)。当您在运行时在代码中创建控件时,您必须自己完成(正如您所发现的)。 (2认同)