PDA

Ver la Versión Completa : A component named XXXXX already exists.. al mostrar más de una ventana de reportes


sitrico
30-05-2005, 23:48:50
El caso es el siguiente:

Quisiera permitir al usuario "ver" más de un reporte (QReport.preview) desde mi aplicación. Me explico la aplicacion tiene n reportes todos basados en un mismo Objeto tQReport y para mostrar uno sólo basta con que haga lo siguiente:


Var
r : tMiQReport;
Begin
r := tMiQReport.Create(self);
try
r.Preview;
Finally
r.free;
End;
End;


Si "se supone" que el preview crea un formulario no modal (de hecho puedo seguir trabajando con la aplicación sin problemas manteniendo el reporte abierto). Debería poder crear otro formulario no modal simplemente llamando al código anterior y tener 2 reportes, pero al hacerlo me salta la excepción:

A component named XXXXX already exists

Supongo que tendrá que ver con el formulario del preview, pero no veo la razón

¿ Alguien sabe como solucionar esa situación ?

PD. uso D7 con QR 4.03pro y por ahora el visor predeterminado.

En este hilo hay un problema similar pero con un sólo reporte (http://www.clubdelphi.com/foros/showthread.php?t=12186&highlight=exists)

sitrico
30-05-2005, 23:55:54
Acabo de probar sustituir el "Self" por "Nil" y trabaja perfectamente.


Var
r : tMiQReport;
Begin
r := tMiQReport.Create(nil); // Aqui antes era Self
try
r.Preview;
Finally
r.free;
End;
End;


¿ Esta solución podría causar fugas de memoria o algún otro problema ?

Lepe
31-05-2005, 17:44:01
En principio tu codigo está bien, pero te aviso de los efectos que puede causar para que no te vuelvas loco buscando los fallos.

Suponiendo que tienes un boton (BtnInforme) en la ventana TClientes, que su código es este:

procedure TClientes.BtnInformeClick(...);
Var
r : tMiQReport;
Begin
r := tMiQReport.Create(nil); // Aqui antes era Self
btnInforme.Enabled:=false;
try
r.Preview;
Finally
freeandnil(r);
btnInforme.Enabled:=true;
End;
End;


El problema viene en el comando Preview, PreviewModal, PreviewModeless, depende del que se use, el código se queda pausado en esa linea o no; y esto trae efectos colaterales.

Si usas Preview, el código se queda pausado en esa linea, si intentas cerrar la ventana Clientes antes que la ventana del quickreport, al cerrar el quickReport obtendrás una violacion de memoria, ya que intentará acceder a la ventana Clientes para continuar el código justo despues de r.Preview, y como esa ventana se ha cerrado, crashhhh.

Una posible Solución:

procedure TclientesCloseQuery(...)
begin
CanClose := btInforme.Enabled;
if not CanClose then
ShowMessage('Cierre el informe');
end;


Si usas PreviewModeLess, el código no se queda pausado en r.Preview, por tanto, el boton de mostrar el informe se habilita de nuevo, y si lo pulsas otra vez, obtendrás el mensaje "component XXX already exist"

Por supuesto tambien depende del tipo de interfaz que estes usando MDI/SDI y de otras consideraciones de diseño que son dificiles de explicar por aqui.

La variable 'r' Donde la tienes declarada, ¿Dentro de un procedimiento local, o en la seccion private/public de un Form?

Cuando quieres abrir el segundo informe.... ¿desde donde se haría? ¿desde el mismo boton?

Un saludo

sitrico
01-06-2005, 20:23:39
Comienzo por el final.

La variable 'r' Donde la tienes declarada, ¿Dentro de un procedimiento local, o en la seccion private/public de un Form?
La declaro dentro del procedimiento local.

Cuando quieres abrir el segundo informe.... ¿desde donde se haría? ¿desde el mismo boton?
En realidad todos los reportes estan enlazados a una unica acción (TAction.Execute) "EmitirInforme" y con un Case Sender.tag of decido que reporte generar.

Si usas Preview, el código se queda pausado en esa linea, si intentas cerrar la ventana Clientes antes que la ventana del quickreport, al cerrar el quickReport obtendrás una violacion de memoria, ya que intentará acceder a la ventana Clientes para continuar el código justo despues de r.Preview, y como esa ventana se ha cerrado, crashhhh.

Si, uso preview y pensé que ocurriria el crashhhh al cerrar la aplicación con un reporte abierto, pero (debe ser por el bloque try..Finally) al cerrar la aplicación se libera(n) apropiadamente el(los) formulario(s) preview y todo parece funcionar bien (a pesar que uso Win XP ;) ).

En realidad lo que se libera al final del procedimiento (r.free) es el QReport y no el formulario QRPreview (que si debe tener el owner apropiadamente asignado).

De todas maneras voy a seguir haciendo pruebas para ver si en alguna situación ocurre un problema.

Lepe
02-06-2005, 11:06:47
Si, uso preview y pensé que ocurriria el crashhhh al cerrar la aplicación con un reporte abierto, pero (debe ser por el bloque try..Finally) al cerrar la aplicación se libera(n) apropiadamente el(los) formulario(s) preview y todo parece funcionar bien (a pesar que uso Win XP ;) ).


Ahhhh, amiiiiiigo, la ventana del boton es el form principal, por eso no obtienes mensajes de errores.

De todas formas, al intentar abrir 2 preview del mismo informe seguirá dando el error, Tendrás que controlar de alguna forma los informes que ya se estan mostrando.


Un saludo

sitrico
02-06-2005, 19:42:32
Acabo de probar sustituir el "Self" por "Nil" y trabaja perfectamente.


r := tMiQReport.Create(nil);


Asignando el owner del reporte a "nil" puedo abrir cuantas ventanas quiera

¡ y no da errores !

vsalomons
16-01-2007, 20:37:14
Pues yo hice lo siguiente despues de leer sus sugerencias
igual a alguien le funciona la idea

Cuatro cosas importantes
1 La variable de tipo reporteador debe ser declarado local en el procedimiento del boton.

2 Usar la cracion con nil para q pueda crearse muchas instancias

r := tMiQReport.Create(nil);


3 crear un visor idependiente personalizado de quickreport
donde puedas manipular la creacion y destruccion del formulario
y en donde igualmente se crea el formulario como (nil), hay temas q explican como crear este tipo de visualizadores personalizados,
Hay q procurar q el formulario se autodestruya al final.
Action := caFree;

4 la llamada del preview se valida con un finally

try
r.Preview;
Finally
r.free;
End;



Salu2