2012-09-26 15 views
6

MainForm crea algunos objetos Frame secundarios en el tiempo de ejecución para mostrar varios paneles de opciones.Diferencias en la inicialización de formulario entre Delphi y Lazarus?

Aquí hay un constructor típico para una de esas clases de trama (cada uno de ellos se extienden 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; 

Este código funcionó bien en Delphi (si es o no era la manera correcta de hacer las cosas), pero el el mismo código en Lazarus sigue arrojando una excepción EInvalidOperation, porque el control (TEdit) todavía no tiene asignada una "ventana" principal (rsControlHasNoParentWindow), lo que de hecho tiene sentido cuando examino el código porque el padre no parece estar asignado hasta que se llame al constructor.

Este es el código en la MainForm inicializa la estructura secundaria:

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; 

Así puede alguien explicar si hay diferencias importantes entre Delphi y Lázaro por lo que la secuencia de inicialización forma?

¿Y cuál sería la forma más estándar de resolver este tipo de problema de orden de inicialización? En comparación con otros idiomas con los que estoy más familiarizado, puede haber diferentes estrategias para resolver dichos errores. Podría agregar otro parámetro al constructor, o si hay un método que recibe el nombre de post constructor pre-dibujarlo en la pantalla que podría anular podría reubicar ese código, o simplemente hacer un método de ayuda y llamarlo después de que se llame a setParent. ¿Alguna de las mejores prácticas en particular aquí?

Editar]: parece que esto puede ser específico para TEdit de alguna manera. Parece que las líneas que inicializan el estado para las casillas de verificación no tienen el mismo problema. ¿Podría ser solo un error en Lazarus?

+0

No sé si eso soluciona el problema, pero establezca Create heredado (AOwner); en el procedimiento de creación. – Ravaut123

+0

Pruebe el código simple * TEdit.Create (nil) .Text: = '12345' *; Este código crea la edición sin padres y le asigna algunos subtítulos. Si esto funciona en VCL pero no en LCL, entonces eso significa que son padres diferentes. También tenga en cuenta que LCL es solo un contenedor contra alguna biblioteca de kits de herramientas. Hay LCL sobre GTK +, LCL sobre Qt y quién sabe qué más. Quizás puedas cambiar el back-end de LCL a otra biblioteca y arreglarlo. O tal vez no. –

+0

Le di una oportunidad, pero no puedo duplicar este problema (lazarus 0.9.30.4). –

Respuesta

1

Después de una mayor experimentación, he podido resolver la mayor parte del problema inmediato de bloqueo al agregar una línea para configurar el elemento primario del TEdit como el Marco (frente a la configuración del elemento primario del Marco). De este modo:

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

Pero todavía me encanta para comprender mejor por qué esto es "a veces" se necesita.

editar: si bien esto soluciona la posibilidad de establecer texto en un TEdit, esto no soluciona el código de autosizing que tengo que itera a través de los componentes y cambia el tamaño de cualquiera que sean casillas de verificación. Aparentemente, el formulario que no tiene su grupo primario sigue siendo un "tipo de" problema.

edit2: Agregar un segundo parámetro al constructor y configurar el elemento principal para el formulario completo en el constructor parecía eliminar la necesidad de establecer el elemento primario para el TEdit por completo.

+2

Esto casi siempre es necesario cuando crea un control visual (como un 'TEdit'). Tiene contenido visual, por lo que necesita un lugar para pintar ese contenido, y eso está en 'Parent.Canvas'. El método de transmisión DFM hace esto automáticamente (y puede ver el 'linaje' o' orden principal' de los controles secundarios en la Vista de estructura o viendo el DFM como texto y observando los niveles de sangría). Cuando crea el control en código en tiempo de ejecución, tiene que hacerlo usted mismo (como ha descubierto). –