PDA

Ver la Versión Completa : Destruir Qrlabels creados en tiempo de ejecucion


Ade
08-10-2006, 02:30:50
Mi problema es q creo los label en tiempo de ejecucion, algo asi:

for i := 1 to NumCampos do begin
With TQRLabel.Create( Self ) do
begin
campo:=ObtienePalabra(QRLabelnew.caption, ',', i);
longitud:= length(campo);
Name := 'QRLabel' + IntToStr(i);//'txPorc' + IntToStr(aListas[i]);
AutoSize := true;
Font.Name := 'Courier New';
Font.Style := [fsBold];
Height := 17;
Left := nCol;
Top := 32;
Width := longitud;
Caption := campo;
Parent := ColumnHeaderBand1;
nCol:= nCol+(longitud*7);
end;

y cuando cierro el informe y vuelvo a realizar otro claro pues se duplica label1,label2, segun el nº d campos, y ahi me da error, me dice:

A component named Qrlabel1 already exists

como puedo una vez cerrado el informe eliminar los qrlabel creados en tiempo de ejecucion??
he probado en el onclose del fom q alberga el quicrep, hay alguna manera de saber cuando se cerró?
Tambien he probado, en el boton donde llamo a QuickRep2.Preview, tras esto hacer:


InformeProveedores2.QuickRep2.Preview;
total:=InformeProveedores2.ComponentCount;
totalbucle:= total-1;
for i:=0 to totalbucle do
begin
if InformeProveedores2.Components[i] is TQRLabel then
begin
showmessage(InformeProveedores2.Components[i].name);
{TQRLabel(InformeProveedores2.Components[i]).Destroy; aqui es cuando falla, hay solo un Tqrlabel funciona, lo destruye, pero si hay mas me da error}
end;
end;
end;



el error:
raised exception class EListError whit message 'list index of boun(7)'
deciros q el 7 creo q es el valor de i en ese momento, es decir el elemento q deberia destruirse ( sino e suna coincidencia )

Saludos y espero me puedan ayudar



Saludos

dec
08-10-2006, 02:40:44
Hola,

Podrías utilizar un objeto "TList" o "TObjectList" que instanciaras en una variable "global", o que estuviera dentro del "formulario de reportes" (nunca usé uno), es decir, suponiendo que su declaración fuera similar a un formulario normal y corriente, algo así:


type
TForm1 = class(TForm)
private
FQrLabels: TList;
end;


Eso te permitiría ir creando instancias de "TQrLabel" e ir añadiendo sus referencias al objeto "TList" o "TObjectList". Al cerrarse el formulario o cuando estimaras más conveniente sería cuestión de liberar el objeto de marras. Ahora mismo no recuerdo si con "TList" basta con liberar dicho objeto o hay que "recorrer" la lista y liberar cada una de los objetos que contiene. Lo mismo te digo para "TObjectList". Tendrás que investigar o algún compañero nos sacará de dudas.

Por otro lado, el error que refieres más arriba es bastante común, y es que, en estos casos en que recorremos los componentes de un formulario, por ejemplo, y vamos liberando algunos de ellos (dependiendo de X condición), hemos de iterar por dichos elementos con un bucle al revés que como suele hacerse, es decir, algo así:


for i := ComponentCount downto 0 do
begin
// lo que tengamos que realizar
end;

Ade
08-10-2006, 02:59:54
ok Dec, muchas gracias por tu ayuda , asi ya sale lo que queria:

for i:=(InformeProveedores2.ComponentCount-1) downto 0 do
begin
if InformeProveedores2.Components[i] is TQRLabel then
begin
if InformeProveedores2.Components[i].name <>'QRLabelnew' then
TQRLabel(InformeProveedores2.Components[i]).Destroy;
end;
end;

Pero aun asi, he de aprender a utilizar un objeto "TList", ya q nunca lo he hecho :eek:
Saludos

dec
08-10-2006, 03:56:42
Hola,


Pero aun asi, he de aprender a utilizar un objeto "TList", ya q nunca lo he hecho


Bueno, oyes, tampoco, si te va bien con la solución que encontraste... por otro lado dicen que el saber no ocupa lugar (es mentira). Depende de lo que traigas entre manos pues lo mismo sí te interesaría utilizar la clase "TList"... acaso algún compañero puesto en esto de los "reportes" pueda arrojar un poco de luz sobre el asunto. :)

Ade
08-10-2006, 04:07:40
La verdad es q una vez q funciona asi, asi se queda :D pero digamos q lo tengo pendiente pues he leido ya varios hilos relacionados, tendre q buscar primero un buen libro, manual o hilo en el q se entre en detalle.

Segun se seleccione en un groupbox (lleno de checkbox) los campos que se quieren mostrar en un dbgird (junto con sus datos obviamente) con el nº de campos seleccionados sera el nº de columnas del quickrep, y ya te digo lei que para eso era mejor Tlist pero dandole vueltas encontre otra forma, jejjje
veremos a ver si en un futuro no es un problema,
Saludos y gracias

dec
08-10-2006, 04:36:11
Hola,

Bueno. Piensa que la descripción de la clase "TList" dice así:


TList stores an array of pointers.


Ni más, ni menos. Bueno. En realidad esa es la descripción corta, la "larga" dice como sigue:


TList, which stores an array of pointers, is often used to maintain lists of objects. TList introduces properties and methods to

- Add or delete the objects in the list.
- Rearrange the objects in the list.
- Locate and access objects in the list.
- Sort the objects in the list.


Vamos, que tampoco tiene mucho misterio, como suele decirse, me parece a mí... :)

De todos modos, parece que "TObjectList" pone la cosa todavía un poco más interesante:


TObjectList maintains a list of (owned) objects.

Unit

Contnrs

Description

Use TObjectList to store and maintain a list of objects. TObjectList provides properties and methods to add, delete, rearrange, locate, access, and sort objects. If the OwnsObjects property is set to true (the default), TObjectList controls the memory of its objects, freeing an object when its index is reassigned; when it is removed from the list with the Delete, Remove, or Clear method; or when the TObjectList instance is itself destroyed.

Lepe
08-10-2006, 19:46:28
Es que... con un TObjectList sería muchiiiiisimo más facil, Sin necesidad de bucles, y pudiendo destruirlos y crearlos a voluntad:



//Cuando lo necesites, creas el TObjectList;
if not Assigned(Lista) then
Lista := TObjectList.Create(true);

// Al crear los labels, los añadimos a la lista
var q:TQRLabel;
for i := 1 to NumCampos do begin
q := TQRLabel.Create( nil ); // nadie lo destruye, lo haremos nosotros
With q do
begin
campo:=ObtienePalabra(QRLabelnew.caption, ',', i);
longitud:= length(campo);
Name := 'QRLabel' + IntToStr(i);//'txPorc' + IntToStr(aListas[i]);
AutoSize := true;
Font.Name := 'Courier New';
Font.Style := [fsBold];
Height := 17;
Left := nCol;
Top := 32;
Width := longitud;
Caption := campo;
Parent := ColumnHeaderBand1;
nCol:= nCol+(longitud*7);
Lista.Add(q);
end;

// Cuando quieras destruirlos:
FreeAndNil(Lista); // todos..... los qrlabels y la propia lista.

// Si solo quieres destruir los labels:
Lista.Clear;


Saludos