Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences in Form Initialization between Delphi and Lazarus?

MainForm creates some secondary Frame objects at runtime to display various option panels.

Here's a typical constructor for one of those frame classes (they each extend 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;

This code worked fine in Delphi (whether or not it was the right way to do things), but the same code in Lazarus keeps throwing an EInvalidOperation exception, because the control (TEdit) has no parent "window" assigned yet (rsControlHasNoParentWindow), which actually kind of makes sense when I examine the code because the parent doesn't appear to be getting assigned until after the constructor is called.

Here is the code in MainForm the initializes the secondary frame:

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;  

So can anyone explain whether there's any important differences between Delphi and Lazarus as far as form initialization sequence?

And what the most standard way to resolve this type of initialization order problem would be? Comparing to other languages I'm more familiar with, there might be different strategies to resolve such errors. I could add another parameter to the constructor, or if there's a method that gets called post constructor pre-drawing it on the screen that I could override I could relocate that code, or just make a helper method and call it after setParent gets called. Any particular best practice here?

Edit]: It appears this may be specific to TEdit in some way. It looks like the lines initializing the state for checkboxes are not having the same issue. Could this just be a bug in Lazarus?

like image 593
Jessica Brown Avatar asked Sep 26 '12 04:09

Jessica Brown


1 Answers

After further experimentation, I have been able to solve most of the immediate problem of it crashing by adding a line to set the parent of the TEdit to be the Frame (versus setting the parent of the Frame). Like so:

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

But I'd still love to understand better why this is "sometimes" needed.

edit: while this fixes being able to set text on a TEdit this doesn't fix the autosizing code I have that iterates through the components and resizes any that happen to be checkboxes. Apparently the form not having it's parent set is still "sort of" a problem.

edit2: Adding a second parameter to the constructor and setting the parent for the entire form in the constructor seemed to eliminate the need to set the Parent for the TEdit's entirely.

like image 183
Jessica Brown Avatar answered Nov 13 '22 05:11

Jessica Brown