Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Lazarus, FreePascal, Kylix, etc. (https://www.clubdelphi.com/foros/forumdisplay.php?f=14)
-   -   Como abrir forms dentro de otro form (https://www.clubdelphi.com/foros/showthread.php?t=90694)

anubis 15-08-2016 02:11:39

Como abrir forms dentro de otro form
 
Hola amigos,

Como he visto que en varios post preguntando lo mismo para lazarus, voy a aportar lo que he recogido y resumido de otros post.

En primer lugar colocamos en el form principal un panel vacio, en la propiedad align le asignais alClient.

Si queremos que, al pulsar un boton, se abra el form debeis poner:

Código Delphi [-]
procedure TPrincipal.SpkLargeButton8Click(Sender: TObject);
begin
   if not assigned(fproveedores) then //Para verificar que no ha sido asginado/abierto el form y no lo abra mas de una vez.
   begin
   fproveedores:=tfproveedores.Create(application);
   fproveedores.Parent:=panel; //Asignamos parent al panel para que se abra dentro de él.
   fproveedores.Show;
   end;
end;

En las propiedades del form que queremos abrir, le tenemos que asignar:
Código:

align:=alNone
BorderStype:=bsSizeable
FormStyle:=fsNormal

En el evento OnClose del form le poneis
Código Delphi [-]
fproveedores.nil
, para que quede desasignado y podamos abrirlo despues.

Con eso ya nos abrira el form dentro del panel.

Una puntualizacion adicional.
Como en mi caso tengo algun problema a la hora de maximizar o cambiar el tamaño porque no refresca bien, lo que hice fue, meter en la clausula uses del form, vinculo con el form principal asi, a la hora de hacer un onResize, haga un refresh del panel.
Código Delphi [-]
procedure Tfproveedores.FormResize(Sender: TObject);
begin
  principal.contenedor.refresh;
end;

Espero que a alguien le sirva este pequeño resumen.

Gracias

Casimiro Notevi 15-08-2016 11:15:13

Cita:

Empezado por anubis (Mensaje 507676)
Código Delphi [-]
 Fproveedores.nil

Eso no libera la memoria, debes hacer Fproveedores.Free

AgustinOrtu 15-08-2016 18:44:38

Tiene owner el objeto Application. Así que se destruye al final de todo. Así que en la práctica es un memory leak porque está la referencia al form hasta que no se destruye Application.

Básicamente se crea un form nuevo cada vez que se dispara el evento del botón. Y cuando se cierra queda oculto y como la referencia original es nil, not assigned evalúa a true

Lo suyo es evitar las variables globales; crear, mostrar, operar el form, y destruirlo cuando no se necesita más. Como cualquier objeto, por ejemplo cuando se usan stream siempre se liberan cuando ya no hace falta

Ahora es cierto que hay casos en los que un form, frame o cualquier control se incrusta dentro de otro y el tiempo de vida es el mismo que el de su parent. En ese caso lo ideal es crearlos en el constructor y destruirlos en el destructor. Lo mismo que un dbgrid, un string grid, un ListView, etc. Código que anda chequeando por nil termina cansando
Lo justo es asegurarse de que todo los controles estén propiamente inicializados.

Por ejemplo en tu código no preguntas si el botón esta asignado. Así debería ser siempre con todos

dec 15-08-2016 18:47:53

Hola,

Cita:

Empezado por AgustinOrtu (Mensaje 507697)
[...]Código que anda chequeando por nil termina cansando [...]

¡De acuerdo en todo y en lo citado! :)

anubis 16-08-2016 22:58:19

Gracias por las respuestas.
Teneis toda la razon y ademas aplastante.
La idea de poner solo form.nil, es porque si meto form.free en el evento onclose como recomedabais, a la hora de cerrar el formulario da error de violacion. entiendo que estas intentando liberar un formulario creado desde el mismo sitio que lo estas cerrando asi que no entiendo entonces donde se debe de poner.
Por otro lado amigos, nose si hay alguna forma de saber si un formulario esta abierto (no asignado) para poder meter en ese punto el form.free.

Perdonad la ignorancia, de momento no he usado nunca los constructores, pero veo que es diferente a crearlos.:(.

Sobre asignar el boton que abre el formulario ademas, quiero pensar, del form asignado, como le digo que el boton esta asignado para que no deje pulsarlo mas veces, si tengo que tener en cuenta que lo debe de desasignar cuando el formulario se cierre?

AgustinOrtu 16-08-2016 23:35:12

En el OnClose le pones Action caFree y el framework ya se encarga de liberarlo.

Ese AV se produce porque luego de ejecutar tu evento TForm sigue haciendo algunas cosas en su método DoClose

ecfisa 17-08-2016 04:09:07

Cita:

Empezado por anubis (Mensaje 507779)
...
Por otro lado amigos, nose si hay alguna forma de saber si un formulario esta abierto (no asignado) para poder meter en ese punto el form.free.

Hola Anubis.

Si para determinar si el formulario está abierto o cerrado, usas el modo
Código Delphi [-]
  if not Assigned(fproveedores) then
  begin
    fproveedores := Tfproveedores.Create(...);
    ...
o, con el mismo resultado:
Código Delphi [-]
  if fproveedores = nil then
  begin
    fproveedores := Tfproveedores.Create(...);
    ...
No te va a alcanzar con liberar el segundo formulario, también deberás poner el valor nil en la variable (fproveedores) al cerrarlo o destruirlo.

Tal vez estos enlaces te aclaren mas el punto:
Saludos :)

anubis 18-08-2016 01:54:10

Se agradece.

Entonces si le añado como decis, en el evento onclose del formulario fproveedores, closeaction:=cafree, y luego fproveedores:=nil, ya no estoy dejando sin cerrarlo y encima liberarlo.


La franja horaria es GMT +2. Ahora son las 14:00:06.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi