Различия в инициализации форм между Delphi и 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;

Этот код отлично работал в 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?


person Jessica Brown    schedule 26.09.2012    source источник
comment
Я не знаю, решит ли это проблему, но установите унаследованный Create (AOwner); в процедуре создания.   -  person Ravaut123    schedule 26.09.2012
comment
Попробуйте простой код TEdit.Create (nil) .Text: = '12345'; Этот код создает редактирование без родителей и присваивает ему заголовок. Если это работает в VCL, но не в LCL - это означает, что они отличаются от родительского. Также обратите внимание, что LCL - это всего лишь оболочка для некоторой библиотеки инструментария. Есть LCL поверх GTK +, LCL над Qt и неизвестно что еще. Возможно, вы можете переключить бэкэнд LCL на другую библиотеку и исправить это. А может и нет.   -  person Arioch 'The    schedule 26.09.2012
comment
Я попробовал, но не могу дублировать эту проблему (lazarus 0.9.30.4).   -  person Sertac Akyuz    schedule 27.09.2012
comment
Я попытался воссоздать ошибку в новом приложении с нуля, но не смог сделать это там, как это было в проекте, импортированном из delphi. Я предполагаю, что, возможно, настройка проекта или параметр компилятора должны отличаться в проекте, который я импортировал из Delphi.   -  person Jessica Brown    schedule 27.09.2012


Ответы (1)


После дальнейших экспериментов я смог решить большую часть непосредственной проблемы его сбоя, добавив строку, чтобы установить родительский элемент TEdit как Frame (вместо установки родительского элемента Frame). Вот так:

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

Но мне все равно хотелось бы лучше понять, зачем это «иногда».

edit: хотя это исправляет возможность устанавливать текст в TEdit, это не исправляет имеющийся у меня код автоматического изменения размера, который выполняет итерацию по компонентам и изменяет размеры всех, которые являются флажками. По-видимому, форма, не имеющая родительского набора, все еще "своего рода" проблема.

edit2: добавление второго параметра в конструктор и установка родительского элемента для всей формы в конструкторе, казалось, избавили от необходимости полностью устанавливать родительский элемент для TEdit.

person Jessica Brown    schedule 26.09.2012
comment
Это почти всегда требуется при создании визуального элемента управления (например, TEdit). У него есть визуальный контент, поэтому ему нужно где-то нарисовать этот контент, и это на Parent.Canvas. Метод потоковой передачи DFM делает это автоматически (и вы можете увидеть lineage или parent order дочерних элементов управления в представлении структуры или просмотрев DFM как текст и наблюдая за уровнями отступов). Когда вы создаете элемент управления в коде во время выполнения, вы должны делать это самостоятельно (как вы обнаружили). - person Ken White; 26.09.2012