Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Problemas con TList (https://www.clubdelphi.com/foros/showthread.php?t=52346)

air_erik 17-01-2008 22:54:07

Problemas con TList
 
Hola, resulta q quiero editar los datos de una tabla de base de datos, y bueno quiero hacerlos dinamicamente, cuando creo los TList de TLabels y de TEdit, me muestra todo bien, pero cuando quiero guardar las modificaciones, me saca un error q dice "List index out of bound (0)".
Pero eso no es todo, cuando vuelvo a ejecutar y logra guardar, me guarda valores q imagino quedaron residentes en memoria, q son distintos a los q modifique en los edit creados.

Finalmente cuando cierro el form, quiero destruir las listas y me saca error de acceso o violación.

Este es el codigo:
por favor ayudenme con sugerencias.

Código Delphi [-]
unit ventana_ver_refrigerio;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, DBTables;
type
Twindow_ver_refrigerio = class(TForm)
Label5: TLabel;
sql01: TQuery;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Label3: TLabel;
procedure FormShow(Sender: TObject);
procedure crear_listas(lista_etiquetas, lista_ed_cantidades, lista_ed_costos, lista_codigos: TList);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
window_ver_refrigerio: Twindow_ver_refrigerio;
FLabelList2, FeditList, FeditList2, FLabelList: TList;
implementation
{$R *.dfm}
procedure Twindow_ver_refrigerio.FormShow(Sender: TObject);
begin
FLabelList:=TList.Create;
FLabelList2:=TList.Create;
FEditList:=TList.Create;
FEditList2:=TList.Create;
crear_listas(FLabelList, FEditList, FEditList, FLabelList2); // Crea etiquetas y cuadros de edición y los guarda en listas
Button1.Enabled:=TRUE;
end;
procedure Twindow_ver_refrigerio.crear_listas(lista_etiquetas, lista_ed_cantidades, lista_ed_costos, lista_codigos: TList);
var
codigos, etiquetas: TLabel;
edit_cant: TEdit;
edit_costo: TEdit;
i: Integer;
begin
i:=1;
sql01.Close;
sql01.SQL.Clear;
sql01.SQL.Add('SELECT * FROM Insumos;');
sql01.Open;
sql01.First;
While not sql01.Eof do
begin
etiquetas:=TLabel.Create(Self);
etiquetas.Caption:=Format(sql01.FieldByName('detalle').asString, [i]);
etiquetas.Parent:=Self;
etiquetas.Font.Charset:=DEFAULT_CHARSET;
etiquetas.Font.Color:=clWhite;
etiquetas.Font.Height:=-13;
etiquetas.Font.Name:='MS Sans Serif';
etiquetas.Font.Pitch:=fpDefault;
etiquetas.Font.Size:=10;
etiquetas.Font.Style:=[fsBold];
etiquetas.Left:=8;
etiquetas.Top:=50+i*20;
lista_etiquetas.Add(etiquetas);
edit_cant:=TEdit.Create(Self);
edit_cant.Text:=sql01.FieldByName('cantidad_stock').asString;
edit_cant.Parent:=Self;
edit_cant.Left:=310;
edit_cant.Width:=33;
edit_cant.Top:=50+i*20;
lista_ed_cantidades.Add(edit_cant);
edit_costo:=TEdit.Create(Self);
edit_costo.Text:=Format(sql01.FieldByName('costo').asString, [i]);
edit_costo.Parent:=Self;
edit_costo.Left:=235;
edit_costo.Width:=33;
edit_costo.Top:=50+i*20;
lista_ed_costos.Add(edit_costo);
codigos:=TLabel.Create(Self);
codigos.Caption:=Format(sql01.FieldByName('cod_ins').asString, [i]);
codigos.Parent:=Self;
codigos.Visible:=FALSE;
lista_codigos.Add(codigos);
i:=i+1;
sql01.next;
end;
end;
procedure Twindow_ver_refrigerio.Button2Click(Sender: TObject);
begin
window_ver_refrigerio.Close;
FlabelList:=nil;
FLabelList.Free;
FLabelList2:=nil;
FLabelList2.Free;
FEditList:=nil;
FEditList.Free;
FEditList2:=nil;
FEditList2.Free;
FLabelList.Destroy;
FLabelList2.Destroy;
FEditList.Destroy;
FEditList2.Destroy;
end;
procedure Twindow_ver_refrigerio.Button1Click(Sender: TObject); //Boton para guardar las modificaciones realizadas en los cuadros de edición
var
cod_ins: TLabel;
cantidad, costo: TEdit;
i, j, k: Pointer;
ban, h: Integer;
begin
ban:=0;
if Application.MessageBox('Está Seguro que desea Guardar las modificaciones?','Modificación de Refrigerios',1+Mb_IconInformation)=1 then
begin
ShowMessage(IntToStr(FEditList.Count));
for h:=0 to FLabelList.Count-1 do
begin
i:=FLabelList2.First;
j:=FEditList.First;
k:=FEditList2.First;
cod_ins:=FLabelList2.Extract(i);
cantidad:=FEditList.Extract(j);
costo:=FEditList2.Extract(k);
if ((cantidad.Text<>'') and (costo.Text<>'')) then //verificamos q ningun campo de edición esté vacio
begin
sql01.Close;
sql01.SQL.Clear;
sql01.SQL.Add('UPDATE Insumos SET costo='+costo.Text+', cantidad_stock='+cantidad.Text+' WHERE cod_ins='''+cod_ins.Caption+''';');
sql01.ExecSQL;
Button1.Enabled:=FALSE;
end
else
begin
ban:=1;
end;
end;
if ban=1 then ShowMessage('Ningún Campo debe estar vacío, el valor mínimo es CERO');
if ban=0 then ShowMessage('Sus datos fueron guardados con éxito');
end;
end;
procedure Twindow_ver_refrigerio.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FlabelList:=nil;
FLabelList.Free;
FLabelList2:=nil;
FLabelList2.Free;
FEditList:=nil;
FEditList.Free;
FEditList2:=nil;
FEditList2.Free;
FLabelList.Destroy;
FLabelList2.Destroy;
FEditList.Destroy;
FEditList2.Destroy;
end;
end.

Un Saludo Erik

PD: perdon por colocar todo el Unit, pero no quiero q se pierda detalles

cHackAll 17-01-2008 23:10:26

Bienvenido; en primer lugar nunca dejes de utilizar las etiquetas [ delphi ]
Código Delphi [-]
 begin
  begin
   // el código va acá por ejemplo
  end;
 end;

Tambien sería util que nos digas la linea donde se genera el error.

Inicialmente i j k supuestamente es siempre 0... entonces para que usas h??? bueno... con mas datos podría responder "algo".

Saludos

air_erik 17-01-2008 23:25:39

Gracias por la sugerencia.

Bueno i,j,k son punteros q apuntan a primer elemento de cada lista (son 3 listas) y h es un entero q ayuda a recorrer toda la lista e ir guardando en la bd cada item.

En realidad el problema se da cuando presiono el Button1 (con el q guarda los cambios realizados en los valores de edit dinamicos), y el otro problema cuando trato de destruir las LISTAS con el metodo FormClose y el Button2 (Cancelar)

air_erik 18-01-2008 01:48:09

Hola de nuevo, perdonenme el hecho de no poder explicarme bien anteriormente, felizmente corregí muchos errores q tenia.

Ahora la unica pregunta q tengo es:
Como se destruyen los TList.

Cuando hice:

Código Delphi [-]
FlabelList:=nil;
FLabelList.Free;
FLabelList2:=nil;
FLabelList2.Free;
FEditList:=nil;
FEditList.Free;
FEditList2:=nil;
FEditList2.Free;

Funciona bien, pero cuando le agrego

Código Delphi [-]
FLabelList.Destroy;
FLabelList2.Destroy;
FEditList.Destroy;
FEditList2.Destroy;

Me sale error de Vil¡olacion de acceso

Gracias nuevamente

xEsk 18-01-2008 01:58:43

Código Delphi [-]
procedure Twindow_ver_refrigerio.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FlabelList:=nil;
  FLabelList.Free;
  FLabelList2:=nil;
  FLabelList2.Free;
  FEditList:=nil;
  FEditList.Free;
  FEditList2:=nil;
  FEditList2.Free;
  FLabelList.Destroy;
  FLabelList2.Destroy;
  FEditList.Destroy;
  FEditList2.Destroy;
end;
A mi parecer, no tiene mucho sentido lo que haces aquí:
- Pones a nil antes de hacer Free? Lo normal, seria liberar y después ponerlo a nil, pero para hacer esto, es mejor "FreeAndNil(FlabelList);" por ejemplo.
- El destroy no se usa, hehe... esto te va a provocar un error. De ahí que te explote al cerrar el formulario.

Saludos.

air_erik 27-01-2008 15:47:20

xEsk Gracias por la sugerencia, te cuento q en algun lugar lei q primero habia q hacer q el puntero apunte a nil y luego liberarlo, y eso fue lo q hice pero probare la alternativa q me das.

Lo q me gustaria es q me pudieran explicar un poco como funcionan esto de los punteros porq no funciona el destroy, q es lo q hace el free y cual la diferencia entre ambos.

Gracias, Saludos

Lepe 28-01-2008 01:48:32

.Free -> Primero se asegura que el objeto es distinto de nil (puntero nulo), si es distinto, llama a Destroy
.Destroy -> elimina de memoria el objeto, si es un puntero nulo, dará un access violation.

"FLabelList" es de por sí, un puntero. Si le asignas nil y después llamas a Flabellist.Free no hará nada, pero la memoria que tenía asignada ¡¡se queda ahí reservada!! es lo que se llama, dejar el objeto en el limbo, (la memoria queda asignada pero no puedes acceder a esos elementos para nada).

Si después de todo esto, llamas a FlabelList.destroy, estás ordenando liberar la memoria de un puntero nulo, por eso casca.

Tu amigo te diría al contrario, es decir:
FlabelList.Free;
FlabelList := nil;

Si te lo dijo al revés, se le trastornó la neurona ;) :D.

Por supuesto, lo más cómodo, como comodon que es nuestro amigo xEsk: FreeAndnil(FlabelList); es lo que uso siempre

saludos

air_erik 06-02-2008 01:13:24

Gracias Lepe por la aclaración.

te cuento q al principio cuando unicamente hice: FLabelList.Destroy en lugar de hacer el free y mandarlo a nil, igual me genero error de access violation, es por esa razon q no pude usar el Destroy, y no entiendo porq, ya q el puntero no era nulo.

Inicialmente solo era esto, pero sacaba error, la pregunta es porq saca error??, si supuestamente lo unico q hago es destruir el puntero.
procedure Twindow_ver_refrigerio.FormClose(Sender: TObject; var Action: TCloseAction);begin FLabelList.Destroy; FLabelList2.Destroy; FEditList.Destroy; FEditList2.Destroy;end;saludos

Lepe 06-02-2008 10:05:03

La ayuda lo dice bien claro:
Cita:

Do not call Destroy directly. Instead, call Free
Tienes código repetido ahora mismo, en el Button2Click y en el OnClose.

Cuando ordenas cerrar la ventana con .Close, se ejecuta el evento Twindow_refrigerio.FormClose que libera las listas, después se sigue ejecutando el Button2Click que también libera las listas de nuevo, es por ahí que da el error.

Supongo que antes tendrías otros errores de diseño, de ahí que te aparecieran errores.

Saludos

air_erik 09-02-2008 22:49:27

Mi estimado Lepe, gracias por toda la información brindada.

Bueno sobre el error q mencionas, si me percate de ello y lo corregi tiempito atras, y simplemente me quedaban las dudas conceptuales q me las aclarastes.

Muy Agradecido a todos del foro me despido.

Saludos


La franja horaria es GMT +2. Ahora son las 01:31:00.

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