PDA

Ver la Versión Completa : Acceso a objetos de un form desde otro


vicens22
17-09-2018, 22:07:16
Estoy desarrollando con Delphi Tokyo y Firemonkey una aplicación para Android e IOS, y me encuentro con el siguiente problema, que imagino que también sucederá programando en VCL, pero por si acaso lo publico aquí.

Ya me encontré con el mismo problema hace unos meses, pero en ese momento lo pude solventar simplemente poniendo los formularios que contienen los objetos a los que hago referencia como "autocreates" en el project, pero ahora me gustaría poder quitarlos de ahí, ya que ralentizan el arranque de la aplicación en el dispositivo móvil.

Se trata simplemente de poder acceder a objetos (tedit y similares, cambiando por ejemplo su propiedad text), que están en un formulario desde otro, sin que el formulario que contiene esos objetos tenga que ser autocreate. Lo que me ocurre al intentar acceder a sus propiedades es que obtengo un error "Access violation".

He creado un ejemplo simplificando el problema (adjunto los ficheros del mismo).
Son tres unidades/formularios: Main, Form1 y Form2.
Sólo Main está como "autocreate" en el project.
En Main, hay un botón que crea Form1, el cual contiene un objeto tLlabel, un tEdit y un botón que crea Form2.
El error (Access violation) ocurre cuando en este último formulario (Form2), intento modificar las etiquetas .text del label y el edit que se encuentran en Form1 (hay un botón que hace simplemente eso).

Este error no ocurre (y se modifican correctamente los objetos label y tedit), si en el project hago que Form1 sea "autocreate", pero ya he comentado que necesito evitar esto para mejorar el arranque de la aplicación, ya que hay varios formularios en los que me ocurre lo mismo.

Gracias por cualquier ayuda.
Saludos,

Vicens

Caminante
17-09-2018, 22:42:44
Hola


La razon para que funcione al tener los forms como autocreate es que para acceder a los mismos deben estar creados. En tal caso deberias crearlos cuando los necesites (No hay necesidad de que esten en autocreate) y liberarlos despues.


Saludos

vicens22
17-09-2018, 23:14:48
Hola,

Gracias por tu respuesta, pero si revisas el código del ejemplo subido, verás que los dos formularios que no son "autocreate" (form1 y form2) son creados. Primero form1 desde el main y luego form2 desde form1.
Es decir los tres están creados cuando obtengo el error (Access violation).
Aquí tienes el código del procedimiento que utilizo para crear y visualizar los dos formularios:



procedure TfMain.OpenTestForm(cForm: string);

procedure OpenForm(form: TForm);
begin
form.Show;
end;
begin
if cForm = 'form1' then
begin
OpenForm(tfForm1.Create(self));
// fForm1.Show; // Si fForm1 es autocreate
end
else if cForm = 'form2' then
begin
OpenForm(tfForm2.Create(self));
end
end;

Si tienes oportunidad pruébalo ejecutándolo en Windows y podrás comprobar que como te comento, los tres forms están creados.

Gracias de nuevo.
Saludos,

Caminante
17-09-2018, 23:55:59
Hola


Por desgracia no cuento con una version de delphi donde probar pero viendo el codigo que pusiste no veo forma que referencies a los controles de los formularios ya que no tienes ninguna variable apuntando a ellos. En este caso no sirve usar las variables que se crean automaticamente en la unidad de los formularios.


Podrias cambiar los metodos para que te devuelvan una referencia al formulario creado (Lo que tambien lleva sus riesgos de memoria) y ya con la referencia podrias hacer lo que deseas


Saludos

vicens22
18-09-2018, 00:03:43
Hola,

Lo siento, pero no veo claro como probar lo que propones.
Pero sigo sin entender, porqué si Form1 es autocreate el mismo código funciona sin problema ??

Saludos,

Caminante
18-09-2018, 00:44:59
Hola,

Lo siento, pero no veo claro como probar lo que propones.
Pero sigo sin entender, porqué si Form1 es autocreate el mismo código funciona sin problema ??

Saludos,

Supongo que cuando referencias al formulario lo haces asi:

form1.edit1.text:='Lo que sea'

Al ser forms autocreados la variable form1 ya esta inicializada y puedes usarla sin problemas. Al crear los forms de la otra manera no asignas nada a 'Form1' por eso da errores de memoria.

Podrias probar asi:
procedure TfMain.OpenTestForm(cForm: string);
begin
if cForm = 'form1' then
begin
form1:=tfForm1.Create(self);
fForm1.Show;
end
else if cForm = 'form2' then
begin
form2:=tfForm2.Create(self);
form2.show
end
end;
Lo hice apegandome a tu codigo. Se puede mejorar pero creo que se puede entender la idea.

Saludos

vicens22
19-09-2018, 10:26:35
Efectivamente, tenias toda la razón, ahora sí pude verlo.
No lo veía, aún teniéndolo delante.
Al estar el formulario visible, no caía en que la variable no estaba inicializada.
Ya modifiqué la creación de los formas y pude conseguir lo que pretendía.

Muchísimas gracias por tu ayuda!!!
Saludos