Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Impresión (https://www.clubdelphi.com/foros/forumdisplay.php?f=4)
-   -   A component named XXXXX already exists.. al mostrar más de una ventana de reportes (https://www.clubdelphi.com/foros/showthread.php?t=21875)

sitrico 30-05-2005 23:48:50

A component named XXXXX already exists.. al mostrar más de una ventana de reportes
 
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:

Código Delphi [-]
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

sitrico 30-05-2005 23:55:54

Acabo de probar sustituir el "Self" por "Nil" y trabaja perfectamente.

Código Delphi [-]
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:
Código Delphi [-]
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:
Código Delphi [-]
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.

Cita:

Empezado por Lepe
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.

Cita:

Empezado por Lepe
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.

Cita:

Empezado por Lepe
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

Cita:

Empezado por sitrico
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

Cita:

Empezado por Sitrico
Acabo de probar sustituir el "Self" por "Nil" y trabaja perfectamente.

Código Delphi [-]
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
Código Delphi [-]
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.
Código Delphi [-]
Action := caFree;

4 la llamada del preview se valida con un finally
Código Delphi [-]
 
try
    r.Preview;
Finally
    r.free;
End;


Salu2


La franja horaria es GMT +2. Ahora son las 12:26:43.

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