Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 10-05-2005
jaaron jaaron is offline
Registrado
 
Registrado: abr 2005
Ubicación: Puebla, Mexico.
Posts: 7
Poder: 0
jaaron Va por buen camino
Question Como libero una forma que llame con un show

Tengo un problema que posiblemente sea muy basico pero es que normalmente muestro las formas de forma modal y al final las elimino con un free, pero estoy programando una aplicacion en la cual necesito crear y mostrar las formas no-modales para que el usuario pueda cambiar de una forma a otra, el problema es que la aplicacion va a estar creando y eliminando las formas de forma dinamica por lo que me interesa saber como las mando eliminar ya que al ponerle el free y al mandarlas crear, me toma como si ya estuvieran creadas y se salta a otras partes del codigo

Código Delphi [-]
  procedure TFmenuprincipal.BPRECIOSClick(Sender: TObject);
  begin
     if not(Assigned(Fmenuprecios)) then  //se checa para no volverla a crear
        Fmenuprecios:=TFmenuprecios.Create(Self);
  
     Fmenuprecios.Show;
     Fmenuprecios.SetFocus;            
     Fmenuprecios.Pmenu.Left:=0;
     Fmenuprecios.Pmenu.Height:=50;
  end;

Este es el codigo con el que creo la forma, y pues ya en el OnClose de la forma que mande llamar esta este codigo:

Código Delphi [-]
  procedure TFmenuprecios.FormClose(Sender: TObject;  var Action:TCloseAction);
  begin
     Action:=caFree;
  end;

la cuestion es que cuando se intenta volver a crear ya no entra al Create toma como si ya estuviera creada y se salta al Show y me manda este error:

"Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00000000. Read of address 0000000000. Process stopped. Use Step or Run to continue."

quiero suponer que es porque no libera la forma completamente y no vuelve a crear una nueva y cuando cae al Show o donde le mando las corrdenadas no hay nada creado, o no se, ahi si alguien me puede echar la mano se los agradezco, se que la opcion mas facil seria ocultar la forma, pero se van a crear muchas formas por lo que si necesito estarlas creando y destruyendo, de antemano gracias.
Responder Con Cita
  #2  
Antiguo 10-05-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
No es que no libere completamente el formulario. Recuerda que una variable de tipo objeto es en realidad un puntero al objeto. Al usar Free se libera la memoria asignada al objeto pero el puntero sigue apuntando a una porción de memoria que ya no es válida. En algún momento tienes que volver a poner el puntero en nil. Una comparación como

if Assigned (FMenuPrecios) then

realmente no verifica si el objeto existe o no, únicamente verifica si la referencia a dicho objeto (la variable) es nil o no. Es decir, la comparación es equivalente a:

if FMenuPrecios <> nil then

En el evento OnClose podrías intentar poner

FMenuPrecios := nil;

// Saludos
Responder Con Cita
  #3  
Antiguo 10-05-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
A ver qué tal parece esta opción

Hola,

Donde dije:

"Yo lo he podido solucionar de esta manera, que, probablemente no sea la mejor. En todo caso a ver qué te parece la solución y la explicación que le doy al error que te encuentras."

Debí decir:

Vale. Hasta aquí el típico párrafo en que uno se lava las manos antes de tratar de indicar la solución de un problema, comprendiendo que lo que va a decir puede estar equivocado (como así ha resultado).

Donde dije:

"Primero el error. Este aparece, si no estoy equivocado, porque, efectivamente, al cerrar una vez la "forma" secundaria liberas de la memoria cualquier referencia de esta."

Debí decir:

Hasta aquí más o menos estoy de acuerdo con lo que pensaba antes. Efectivamente, liberas una referencia, pero no cualquier referencia; y no es que se libere la "forma", pero únicamente una referencia a la misma.

Donde dije:

"Luego, al comprobar que no está creada la forma secundaria para crearla de nuevo se produce un error, porque, no está creada, pero tampoco puede crearse, puesto que su tipo ya no existe en la aplicación: ya se liberó."

Debí decir:

Esto es de lo peor, creo. Como bien dice roman, no se comprueba (con "if not Assigned(Form2) then ...") si la forma ha sido o no creada, sino si la referencia a ella es nula ("nil"). Y el tipo de la forma no puede liberarse: puede liberarse una determinada referencia al tipo, o un objeto de dicho tipo, pero no el tipo como tal.

Donde dije:

"La solución puede que pase por declarar una variable del tipo de la forma en donde vayas a emplear esta. Comprobar que no está ya creada una instancia de esta forma (secundaria) en la variable en cuestión. ¿No lo está? Se crea y se muestra la forma. ¿Lo está? Entonces no hace falta mostrarla, sino darla el foco, si es preciso."

Quise decir:

La solución no pasa por ahí, ya está claro, pero, ¿cómo pude pensar lo contrario? En realidad no hay que crear una variable del tipo de la forma, porque dicha variable ya está creada, quiere decirse, podemos utilizarla. Esta variable no guarda la forma como tal, sino una referencia a ella. Lo que debemos comprobar, como dice roman, es que dicha variable no guarda una referencia nula.

Donde dije:

"Utilizamos el evento "OnClose" de la forma secundaria para dar el valor "caFree" a la variable "Action" de tipo "TCloseAction"."

Debí decir:

Vamos a ver... ¿qué pretendía conseguir con esto? Efectivamente, dando el valor "caFree" a la variable "Action" que podemos encontrar en los parámetros del evento "OnClose" de un formulario, ¿qué liberamos? ¿Liberamos la referencia a dicho formulario? ¿El propio formulario? ¿El tipo del formulario? Liberamos la memoria asignada al objeto del tipo del formulario, pero no la referencia a este, la cual seguirá estando disponible... aunque ya no nos servirá, pues esta referencia será nula.

Donde dije:

"Aquí puedes ver un poco de código:"

Código Delphi [-]
       uses
         Unit2; // Contiene el tipo de una "Forma" secundaria
       
       var // Esta variable contendrá dicho tipo
         Formulario2: TForm2; 
       
       procedure TForm1.Button1Click(Sender: TObject);
       begin
         // Si la forma secundaria no se ha asignado aún
         if not Assigned(Form2) then
         begin
           // Utilizamos "Formulario2" para crear la Forma secundaria
           Formulario2 := TForm2.Create(Self);
           Formulario2.Show; // Y la mostramos
         end else // Si la forma secundaria ya ha sido asignada
           Formulario2.SetFocus; // Enfocamos
       end;

Debí decir:

Aquí está el código tanto de la parte en que se crea el formulario o forma como de la sentencia a utilizar en el evento "OnClose" de dicho formulario:

Código Delphi [-]
  
  (* Desde Form1 mostraremos el formulario o forma Form2 *)
  
  uses
    Unit2; // Contiene TForm2
  
  procedure TForm1.Button1Click(Sender: TObject);
  begin
     If not Assigned(Form2) then // Podría ser: if Form2 = nil then
     begin   
       Form2 := TForm2.Create(Self);
       Form2.Show();
     end else
       Form2.SetFocus();
  end;
  
  (* Evento OnClose de Form2 *)
  
  procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
  begin
    Form2 := nil; // Anulamos la referencia a Form2 existente hasta aquí
  end;

Donde dije:

"No creas que me sé explicar todo lo que trato de explicarte a ti (¿Qué es esto?), al menos no todavía, pero el caso es que funcionar parece funcionar. Pruébalo tú a ver qué tal."

Debí decir:

No tengo mucha idea de cómo lo he hecho, pero, tecleando como un poseso he conseguido solucionar el problema, al menos, aparentemente. Tal vez alguien pueda aportar otro punto de vista, pero, tal vez esto pueda ayudarte en algo.
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 10-05-2005 a las 21:41:13. Razón: (corrección del texto)
Responder Con Cita
  #4  
Antiguo 10-05-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Pues me adelanté completamente

Hola,

Lo cierto es que me parecía haber probado a asignar el valor "nil" a la "forma" secundaria en su evento "OnClose". Juraría que lo hize, pero, no puede ser, otra cosa haría y me he confundido.

Efectivamente, roman lleva razón: con darle el valor "nil" en el evento "OnClose" a la forma secundaria el problema se resuelve igualmente, bueno, igualmente no, de una manera más elegante que con "mi solución".

Y además de que mi solución es menos elegante es que no está basada en la teoría que expone german... sino en no sé qué teoría... que así ha salido.

Quiero decir que no comprendo aún muy bien ni lo que ha expuesto roman ni lo que yo mismo he expuesto: tendré que releer los comentarios para tratar de hacerlo. No sé cuántas veces.

Actualización: No he querido borrar el comentario anterior en que trato de aportar una solución al problema aunque dicha solución no fuera acertada del todo, al menos.

He preferido editarlo, de tal modo que se pueda leer en los apartados "Donde dije:" el comentario tal como lo realizé originalmente, y, en los apartados "Debí decir:" lo que, después de leer a roman y tratar de comprender su solución (que es la correcta) he podido comprender y valga la redundancia.
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 10-05-2005 a las 21:40:10. Razón: (ampliar el texto)
Responder Con Cita
  #5  
Antiguo 10-05-2005
jaaron jaaron is offline
Registrado
 
Registrado: abr 2005
Ubicación: Puebla, Mexico.
Posts: 7
Poder: 0
jaaron Va por buen camino
Talking Pues efectivamente, con el nil se soluciona

Como puse en el titulo, ya con el nil se soluciona, de hecho comprobe que crea una forma nueva cada vez que pulso el boton que manda crearla, ya decia yo que iba a ser algo sencillo pero que sino fuera por ustedes me hubiera costado mucho trabajo solucionar, una agradecimiento a ambos tanto por su ayuda y su rapida contestacion, es bueno saber que se puede contar con ayuda cuando se necesite, gracias a ambos.
Responder Con Cita
  #6  
Antiguo 11-05-2005
Avatar de Ohcan
[Ohcan] Ohcan is offline
Miembro Premium
 
Registrado: ago 2004
Ubicación: Madrid (España)
Posts: 119
Poder: 20
Ohcan Va por buen camino
Question FreeAndNil

De la ayuda de Delphi:

Cita:
FreeAndNil procedure

Frees an object reference and replaces the reference with nil (Delphi) or NULL (C++).
Unit
SysUtils
Category
Pointer and address routines
Delphi syntax:
procedure FreeAndNil(var Obj);
C++ syntax:
extern PACKAGE void __fastcall FreeAndNil(void *Obj);
Description
Use FreeAndNil to ensure that a variable is nil (Delphi) or NULL (C++) after you free the object it references. Pass any variable that represents an object as the Obj parameter.
Warning: Obj must be an instance of a TObject descendant.
Entonces... ¿no sería mejor usar siempre ésto en vez del .free?
__________________
La violencia es el último recurso del incompetente. (Salvor Hardin)
Responder Con Cita
  #7  
Antiguo 09-06-2005
jaaron jaaron is offline
Registrado
 
Registrado: abr 2005
Ubicación: Puebla, Mexico.
Posts: 7
Poder: 0
jaaron Va por buen camino
No estoy seguro si libera completamente

Pues soy yo de nuevo con una nueva duda, ya decia yo que era mucha buena suerte que todo saliera bien, el problema que tengo es este:

Como les habia dicho creo la forma de manera dinamica y la muestro con un Show, el primer problema era que no sabia como liberar esa forma, gracias a la ayuda anterior probe con Nil y parecia que todo iba bien, pero....por cuestiones de programacion necesite asignarle el nombre de la forma despues de crear, el problema esta que al crear la forma la primera vez todo funciona bien, la cuestion es que cuando salgo de la forma y la libero con nil, al querer volverla a crear me dice que el objeto con el nombre que asigno ya existe, ahora mi duda, es si realmente la orden Nil libera totalmente la memoria o necesito de algo mas?

Código Delphi [-]
          if not(Assigned(Fpre_captura)) then
          begin
             Fpre_captura:=TFpre_captura.Create(Self);
             Fpre_captura.Name:='Fpre_captura';
         end;     
         Fpre_captura.Show;

y para liberar en el OnClose pongo esto:

Código Delphi [-]
        Fpre_captura:=Nil;

y como no estaba seguro de que nombre creaba, intente quitarle la asignacion del nombre y ver que nombre ponia la segunda vez que se creaba la forma y el nombre que se crea es este: Fpre_captura_1, entonces eso quiere decir que la primera forma todavia se queda en memoria o hace falta algo mas por liberar, ya intente usar freeandnil pero me manda un error de memoria y me cierra la aplicacion, les agradezco su ayuda de antemano.

Última edición por jaaron fecha: 09-06-2005 a las 20:55:52.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 11:25:56.


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
Copyright 1996-2007 Club Delphi