Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Error TStringList creados en tiempo de ejecución (https://www.clubdelphi.com/foros/showthread.php?t=52562)

subzero 24-01-2008 15:44:04

Error TStringList creados en tiempo de ejecución
 
Hola a todos/as....


Nuevamente consultado... Mi problema es el siguiente, tengo una una FORM en la cual tengo incluidos varios componentes dentro de los cuales esta un Combobox, el cual es llenado desde una consulta, ya que es necesario guardar el identificador de los datos que son almacenados en el Combo, declaro una variable de tipo TStringList en Private, y luego a este le digo que se cree en el evento OnCreate de la Forma de esta manera:

Lista := TStringList.Create;

Luego lleno los datos tanto en el combo como en la lista que he creado y hasta aqui todo bien.

Cuando cierro la Form en el evento OnClose libero la variable:

Lista.Free;


El problema surge cuando nuevamente quiero entrar a esta forma pués me indica que hay una excepcion con un error en la violación de la dirección, encerre el codigo con el que hago el llamado en try...except pero sigue apareciendo el error


Agradezo cualquier idea...

ixMike 24-01-2008 15:55:52

¿Podemos ver el código? ¿El OnCreate, el OnClose y el código de llenar el Combo y la Lista? Gracias

subzero 24-01-2008 16:36:04

bueno puse a que el objeto se creara no cuando se crea la forma sino cuando se abre en el evento OnShow de la Form

Código Delphi [-]
Lista := TStringList.Create;

y hasta el momento parece funcionar... Gracias "ixMIKE"

ixMike 24-01-2008 16:59:48

Cita:

Empezado por subzero (Mensaje 260574)
bueno puse a que el objeto se creara no cuando se crea la forma sino cuando se abre en el evento OnShow de la Form y hasta el momento parece funcionar... Gracias ixMike

Es extraño :confused:, bueno, si después hiciera "cosas raras", pues pones lo dices y pones el código, ¿ok? ;)


Salu2.

poliburro 24-01-2008 17:04:43

Si tus formularios no son creados dinámicamente, es decir solo necesitas llamarlos a través de formulario.show, realiza la creación de la variable en el evento Onshow del formulario.

egostar 24-01-2008 17:17:41

Cita:

Empezado por poliburro (Mensaje 260581)
Si tus formularios no son creados dinámicamente, es decir solo necesitas llamarlos a través de formulario.show, realiza la creación de la variable en el evento Onshow del formulario.

Esto me recuerda a algo que comente en el hilo suma de registros. :rolleyes:


Salud OS

subzero 24-01-2008 17:28:48

siguiendo la sugerencia de ixMIKe esto es lo que hago....

Código Delphi [-]
private
  Lista : TStringList;
..............

procedure TForma1.FormShow(Sender: TObject);
begin
  Lista := TStringList.Create;
  /*Aqui lleno tanto la lista como el Combobox*/
  Lista.Clear;
  ComboBox1.Clear;
  with Query do
  begin
    close;
    Sql.Clear;
    Sql.Add('SELECT campo_lista, campo_combo');
    Sql.Add('FROM nombre_tabla');
    open;  first;
    while not (eof) do
    begin
      lista.Add(fieldbyname(campo_lista).AsString);
      combo.Add(fieldbyname(campo_combo).AsString);
      next;
    end;
    close;
 end;  
end;


procedure TForm1.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Lista.Free
end;


Espero que ahora este mucho más claro... saludos!

jachguate 24-01-2008 18:13:17

En primer lugar, recomiendo que el TStringList debiera crearse en el OnCreate del formulario y destruirse en el OnDestroy.

En el OnShow basta con que se quede la sentencia Lista.Clear que por ahora está de mas.

Hasta luego.

;)

poliburro 25-01-2008 21:06:30

Cita:

Empezado por jachguate (Mensaje 260608)
En primer lugar, recomiendo que el TStringList debiera crearse en el OnCreate del formulario y destruirse en el OnDestroy.

En el OnShow basta con que se quede la sentencia Lista.Clear que por ahora está de mas.

Hasta luego.

;)

Eso es correcto solo si el formulario es dinámicoo, de ser estático genera el error que le está sucediendo al amigo, Insisto, debes colocar la creación del stringlist en el evento onshow.

suerte

jachguate 26-01-2008 03:54:46

Cita:

Empezado por poliburro (Mensaje 260985)
Eso es correcto solo si el formulario es dinámicoo, de ser estático

Francamente no estoy seguro de que querés decir con "dinámico" y "estático", pero tampoco veo cuales son los argumentos para que el StringList se cree en el OnShow.

De hecho, creo que podría ser en ambos... siempre depende.

Lepe 26-01-2008 04:23:41

Yo opto por el OnCreate, es lo "más seguro para nuestro código", o bien amarrar bien con FreeAndNil la lista, pero es marear la perdiz en este caso. Si queremos tener una lista en memoria a la misma par que un combo, dará igual cargarla después de crear el form que antes de mostrar el form.

Si lo dejas en el OnShow, basta que hagas un :
form1.hide;
form1.show;
form1.hide;
form1.show;
form1.hide;
form1.show;

Para crear 3 listas en memoria con los datos repetidos, las 2 primeras listas se quedaran en el limbo de RAM.

Y en otro orden..... ¿para qué usas esa lista? ya tienes el combo, podrías utilizarlo para buscar elementos o lo que quieras, mientras no asignes el itemindex del combo, no cambiará la selección del mismo.

Saludos

poliburro 26-01-2008 05:00:39

Cita:

Empezado por jachguate (Mensaje 261137)
Francamente no estoy seguro de que querés decir con "dinámico" y "estático", pero tampoco veo cuales son los argumentos para que el StringList se cree en el OnShow.

De hecho, creo que podría ser en ambos... siempre depende.



Dinámico: El formulario es creado al vuelo. Antes de iniciar la llamada al formulario debe crearse la instancia.

Estático: El formulario es creado al iniciar la aplicación. Al llamarlo, siempre se llama a la misma instancia.

Dinámico. Los elementos se destuyen y construyen con el formulario.

Estático.

Se crean elementos en el evento OnCreate (Elementos creados una sola ocasión)

Se destruyen los elementos al cerrar el formulario.

Al llamar a la misma instancia, debido a que esta no es creada nuevamente, los elementos a los que se intenta acceder ya no existen pues fueron destruidos al cerrar el formulario.

Punto

jachguate 26-01-2008 05:36:31

Cita:

Empezado por Lepe (Mensaje 261144)
Si lo dejas en el OnShow, basta que hagas un :
form1.hide;
form1.show;
form1.hide;
form1.show;
form1.hide;
form1.show;

Tenes toda la razón, Lepe. Cuando he dicho esto:

Cita:

Empezado por jachguate
De hecho, creo que podría ser en ambos... siempre depende.

Es porque estaba pensando que Hide podría disparar el evento OnClose, pero ahora he abierto el delphi y veo que no lo hace. Así, no hay paridad entre la creación y la liberación de la lista, provocando pérdida de memoria.

jachguate 26-01-2008 05:38:50

Cita:

Empezado por poliburro (Mensaje 261150)
Estático.

Se crean elementos en el evento OnCreate (Elementos creados una sola ocasión)

Se destruyen los elementos al cerrar el formulario.

Creo que el problema acá es de concepto. Lo que se crea en el OnCreate, debiera destruirse en el OnDestroy.

Hasta luego.

;)

Lepe 26-01-2008 13:58:05

Completo un poquito más:

Cita:

Empezado por jachguate (Mensaje 261159)
Lo que se crea en el OnCreate, debiera destruirse en el OnDestroy.

Y no tiene nada que ver que se creen dinámicamente o estáticamente las ventanas.

El ciclo de vida es el mismo para ambos tipos de Forms.


En honor a la verdad, poliburro ha detectado el fallo del access violation, pero creo no ha sabido explicarse porque tanto jachguate como yo lo hemos malinterpretado.

1º- Deja el StringList en el oncreate como lo tenías. Liberas la lista en el OnDestroy.

2º- El access violation es problema de cómo usas tus ventanas, no tiene nada que ver con el TStringList.

Si tu ventana se llama FrmClientes (por decir algo) y esa variable la usas en todas tus ventanas, en el Onclose añade:
Código Delphi [-]
procedure TFrmclientes.OnClose(... Action:TCloseAction);
begin 
  action := cafree;
  frmClientes := nil;
end;

cuando necesites usar la ventana de nuevo, comprueba si ya está abierta:
Código Delphi [-]
  if Frmclientes <> nil then
    // ya está abierta
  else
    FrmClientes := TFrmclientes.Create(self);

// y para cerrar la ventana:
 FrmClientes.Close;  // o incluso Frmclientes.Free, ambas funcionaran.

Si no usas la variable FrmCliente en tu aplicación, es decir, creas las ventanas así:
Código Delphi [-]
var f:TFrmClientes;
begin 

   f := TFrmclientes.Create(nil / application / self);

// o bien haces esto en alguna ocasión:
 with TFrmclientes.Create(...) do
 try 


 finally
    Free
 end;

Entonces no puedes usar el evento OnClose para poner la variable FrmClientes a nil, siempre deberías usar FreeandNil(f) o de la variable que uses.

Saludos


La franja horaria es GMT +2. Ahora son las 04:44:49.

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