Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Problema con limite de instancias de objetos (TBitBtn) (https://www.clubdelphi.com/foros/showthread.php?t=62134)

nuk3zito 05-12-2008 00:28:25

Problema con limite de instancias de objetos (TBitBtn)
 
Buenas tardes,
Les comento lo siguiente: Hice un módulo muy padre y toda la cosa que a resumidas cuentas permite a un usuario crear objetos en un contenedor (tpanel - emulando las celdas de excel) pero mi aplicación a pesar de que los objetos se destruyen cuando se dejan de usar ya sea eliminandolos manualmente o cuando se carga otro reporte (es un reporteador realmente)... llega un momento en que me marca "Out of resources"

Mi pregunta es: ¿Existe algún límite configurable desde la aplicación (en este caso, desde alguna directiva de compilación) que resuelva este problema?

Utilizo Windows Vista Bussines, Delphi 2006 y la aplicación es de tipo Win32.

La clase de donde se crean los objetos es heredada de TJvXPButton (de los jedi, aunque con TBitBtn se presenta el mismo problema) con algunas características especiales.

Presiento que está muy "pesado" ese control... pero tengo 3Gb de memoria y cada reporte solo crea 1300 objetos de ese tipo, se corre un reporte a la vez... alguien puede orientarme a la solución? o de plano mi pregunta está muy fumada?

Espero sus aportes y gracias de antemano.

cHackAll 05-12-2008 01:04:17

Como opinion personal; creo que lo que estas haciendo es un Cruft... por qué no pegas un pantallazo de lo que quieres para ver que podemos hacer (de otra forma, claro está).

nuk3zito 05-12-2008 01:21:18

Cita:

Empezado por cHackAll (Mensaje 329791)
Como opinion personal; creo que lo que estas haciendo es un Cruft... por qué no pegas un pantallazo de lo que quieres para ver que podemos hacer (de otra forma, claro está).

Ya veo por que tienes tantos posteos...

Gracias de todos modos por tu aporte.

Alguien puede contestar a mi pregunta original?
¿Existen restricciones de número de instancias o de memoria asignada para tales?

Gracias de antemano

cHackAll 05-12-2008 01:36:32

Cita:

Empezado por nuk3zito (Mensaje 329797)
Ya veo por que tienes tantos posteos...

Gracias de todos modos por tu aporte...

OYE, pero que individuo más antipatico... te perdono porque no sabes lo que dices!

Cita:

Empezado por nuk3zito (Mensaje 329797)
¿Existen restricciones de número de instancias o de memoria asignada para tales? ...

Te aconsejo comprarte unos 80 Gb de RAM y que tengas mucha suerte con ello pues a mi se me desvanecieron mis animos de ayudarte! :mad:

nuk3zito 05-12-2008 01:49:17

Cita:

Empezado por cHackAll (Mensaje 329802)
Te aconsejo comprarte unos 80 Gb de RAM y que tengas mucha suerte con ello pues a mi se me desvanecieron mis animos de ayudarte! :mad:

No importa, no me ayudes (ya he visto como ayudas en otros posteos... uff) y repito... gracias por tu aporte.

Esto es precisamente lo que me temía... que no respondieran a la pregunta original y quisieran desviar el asunto como diciendo: NO SE... PERO SE ME OCURRE QUE...

Ni hablar. :(

P.D. En C# de Visual Studio no tengo problemas con esto... pero lo necesito en Delphi.

egostar 05-12-2008 01:50:37

Cita:

Empezado por nuk3zito (Mensaje 329808)
No importa, no me ayudes (ya he visto como ayudas en otros posteos... uff) y repito... gracias por tu aporte.

Esto es precisamente lo que me temía... que no respondieran a la pregunta original y quisieran desviar el asunto como diciendo: NO SE... PERO SE ME OCURRE QUE...

Ni hablar. :(

Cual desvio, tu preguntaste......

Cita:

Empezado por nuk3zito
alguien puede orientarme a la solución? o de plano mi pregunta está muy fumada?

Y pues se te contesto con lo segundo :rolleyes:

Salud OS

cHackAll 05-12-2008 01:54:45

Cita:

Empezado por nuk3zito (Mensaje 329808)
No importa, no me ayudes (ya he visto como ayudas en otros posteos... uff)...

qué? tan malo soy para esto??? pero por favor; guíame!

Lepe 05-12-2008 07:54:41

La verdad es que con esa actitud, es muy raro que alguien se anime a responderte. Si necesitas hacerlo "a tu manera" basta con decirlo, no hace falta criticar a un valioso miembro de esta comunidad, que dicho sea de paso, rebosa calidad en todos sus mensajes y siempre se aprende algo de él. Si tú no sabes apreciar esa calidad... ejem, es problema tuyo.

¿sólo 1.300 objetos? ¿sólo?, desde luego no es un buen diseño, y precisamente esa es la mejor respuesta que se te puede dar, siempre con ánimo constructivo, como ha hecho cHackAll al brindarte su ayuda, que por cierto, no está obligado a hacerlo.

Saludos

cHackAll 05-12-2008 14:37:47

Cita:

Empezado por nuk3zito (Mensaje 329779)
...o de plano mi pregunta está muy fumada?...

:rolleyes:

Bueno, independientemente de que el iniciador del hilo (en mi opinion), haya sido algo antipatico; creo no poder resistirme a lanzar un par de ideas al aire a ver si son de utilidad; en C# existen los Garbage Collectors que son de gran utilidad, pero a veces ocacionan que el desarrollador pierda conceptos de manejo de memoria y objetos (especificamente su adecuada liberación); nativamente Delphi no consta con lo anteriormente dicho y aunque existen componentes yo tengo mis reservas.

En este caso, es probable que se estén creando los N objetos, y al no ser adecuadamente liberados los mismos sean incrementados en cada ocacion, en dicho contexto habría que analizar el codigo.

Ahora; cuando en mis comienzos hice lo que el inciador del hilo hizo (con fines de edicion de datos), aprendi que ésta no es una buena practica; solamente basta con imaginar que sucedería si Excel usara para cada celda un TEdit...

La solucion mas "facil" es el uso de componentes; StringGrids (como comentaba egostar), TListViews, etc., en un nivel mas experto de programación desarrollar emulaciones y pintados en Lienzos(Canvas)
(Aunque para facilidad de programación tambien existen un buen numero de componentes de terceros que hacen esto).

nuk3zito; si quieres adjuntar un pantallazo (como te sugeri al comienzo) talvez otros miembros te puedan dar ideas (componentes que asemejen comportamiento)... si quieres continar con la actitud inicial pues dudo que obtengas resultados. En mi opinion solo di una critica constructiva para evitarme éste engorroso post.

PD; Si tenemos 80 Gb. de RAM (hipotetico), y conseguimos que nuestro programa tenga acceso al 100%, si el programa tiene Memory Leaks en algun momento dirá "Out of resources".

Un abrazo a egostar y a Lepe.

Saludos

coso 05-12-2008 16:06:20

yo creo que no liberas correctamente los panels creados (un TPanel en memoria tampoco debe ocupar mucho, y 1300 no suena a muchos) o el objeto que sea. De todas maneras, crear un grid de panels tipo excel es algo un poco...cruft...digamos ¿por que no nos explicas mejor que es lo q quieres hacer y te podemos echar mejor una mano?

PD : sin decir nada nuevo : ¿no te iria mejor usar un TStringGrid o un TListView?

luisgutierrezb 05-12-2008 18:26:34

Respuesta a tu pregunta:

NO, no existe un limite configurable.

para crear los objetos que usas? un TList, un arreglo? o como?
ojala puedas poner codigo, a lo mejor es algo que programaste mal o un bug del delphi

nuk3zito 05-12-2008 18:31:46

Que tal,
cHackAll, me disculpo por mi respuesta agresiva, la verdad es que algunas veces estoy a la defensiva cuando presiento que van a desviar el tema (ya me ha pasado muchas veces, son pocas las ocasiones en que he tenido serias dudas) y creo que en esta ocasión esto me llevó a iniciar con el pie izquierdo; aparte de todo, te agradezco por dar una respuesta a lo que necesito.
Mira, si se que el Framework de .NET tiene su Garbage Collector y es bastante eficiente y he supuesto desde que se me presentó el problema que Delphi no maneja adecuadamente su basura, a pesar de que desde el Delphi 2005 lo han estado prometiendo (uso el 2006, desconozco si alguna versión posterior lo maneje adecuadamente). Es precisamente esto lo que quería indagar en este foro, y es que en realidad nunca se acaba la memoria de mi PC y ni siquiera se ve algo de actividad anormal en este aspecto (ni con los 1300 objetos cargados por el usuario en tiempo de ejecución).
A continuación adjunto un pantallazo que muestra un poco del tema de lo que la pantalla debe hacer (en este proyecto no soy el líder, así que recibo órdenes... órdenes de hacer lo mismo que se hizo en C# de manera muy similar en Delphi)



Los botones se colocan en tiempo de ejecución cargadas sus propiedades y propiedades "agregadas" desde una tabla (para eso utilicé la herencia) los cuales al dar click o al llamar su menú contextual hacen o muestran algo. Las rutinas para las llamadas del menú contextual y el código de los eventos es genérico, es decir, se liga a cada "botón" cargado en la pantalla. Las propiedades que se agregaron son tan genéricas como simples variables (accesadas desde sus propiedades obviamente) de tipo integer, string, real, etc.
¿Por que debe ser botón? Porque al usuario se le indica de manera implícita que le puede dar click (algo obvio) aunque no estoy casado con la idea de tener que usar botones, simplemente fue lo que en su momento se nos ocurrió presentar al usuario. Si encuentro otro componente que sea bastante más ligero y que no me presente los mismos problemas, creo que lo utilizaré.

La manera de liberar los objetos una vez que ya no se requeiren en el reporte actual, es de la siguiente manera:

Código Delphi [-]
  for i := 0 to slElementos.Count - 1 do
    if Assigned( slElementos.Objects[i] ) then
    begin
      TObjElemento(slElementos.Objects[i]).Free;
      slElementos.Delete(i);
    end;

Tal vez esto no sea de la manera adecuada. Pero no se de que otra manera debería liberar los objetos... FreeAndNil entiendo que hace lo mismo pero me pone los valores en null, lo cual lo considero innecesario puesto que elimino mis objetos del StringList que utilizo.

Cita:

Empezado por cHackAll (Mensaje 329870)
:rolleyes:
Ahora; cuando en mis comienzos hice lo que el inciador del hilo hizo (con fines de edicion de datos), aprendi que ésta no es una buena practica; solamente basta con imaginar que sucedería si Excel usara para cada celda un TEdit...

Tienes razón al respecto... en este caso el reporte es un mounstruo, se lleva la contabilidad de grandes empresas, pero mi sorpresa no fue que hicieran un reporte así... sino que delphi se sentara con esto. Desde un principio me dejé llevar por la idea de que Delphi sportaría tales procesos como pan comido.

Cita:

Empezado por cHackAll (Mensaje 329870)
:rolleyes:
si quieres continar con la actitud inicial pues dudo que obtengas resultados. En mi opinion solo di una critica constructiva para evitarme éste engorroso post.

Creo que a nadie le gusta que le digan que no sabe programar. La verdad me pareció un comentario muy al aire en vez de crítica constructiva puesto que se supone que Delphi no debereía tener problema con esto.

Lo de la memoria por cierto... la memoria de la instancia de la aplicación no se la pasa creciendo, por lo que ni con 3Gb ni con 80Gb se resolvería el problema. Es por eso que acudí al foro para ver si alguien habría tendio antes un problema similar y ver que diablos pudiera estar pasando.

Aún y los roces que se presentaron desde un principio, agradezco ahora si de manera sincera tu aporte. He tenido buena experiencia con foristas que no buscan desacreditar el trabajo de los posteadores sino que se limitan a tratar de solucionar los problemas y lo otro lo dejan como comentario secundario... espero que con esto me disculpes mi postura inicial.

Gracias. Creo que rediseñaré algunas cosas y si esto funciona se los haré saber.

nuk3zito 05-12-2008 18:33:34

Cita:

Empezado por luisgutierrezb (Mensaje 329899)
Respuesta a tu pregunta:

NO, no existe un limite configurable.

para crear los objetos que usas? un TList, un arreglo? o como?
ojala puedas poner codigo, a lo mejor es algo que programaste mal o un bug del delphi

Que pues Luis, que milagro... creo que te pasaré por messenger el caso, aunque dudo que le tengas solución... esto me huele más a bug y bug de memoria (del ausente Garbage Collector)

egostar 05-12-2008 18:35:22

Cita:

Empezado por nuk3zito (Mensaje 329901)
Que pues Luis, que milagro... creo que te pasaré por messenger el caso, aunque dudo que le tengas solución... esto me huele más a bug y bug de memoria (del ausente Garbage Collector)

:rolleyes::rolleyes::rolleyes:

Ya buscaste bien?

Salud OS

Edito: Hablar de bugs requiere de algo mas que no encontrar una solución a tu problema.

nuk3zito 05-12-2008 18:40:33

Cita:

Empezado por egostar (Mensaje 329902)
:rolleyes::rolleyes::rolleyes:

Ya buscaste bien?

Salud OS

Soy malo para decir sarcasmos (a un lenguaje, por Dios) por este medio.
Entonces si no está ausente, no está funcionando como debe ser. ;)

P.D. El vendedor estrella de Delphi Studio en México me dijo alguna vez: No creas todo lo que dice la cajita.
A lo cual el mismo en esas sesiones se dio cuenta que su comentario no le daba más valor a su producto si no que también abarcaba los bugs no mencionados.

Saludos.

Kipow 05-12-2008 18:46:43

"Siempre hay mas de 1 forma de hacer las cosas y siempre hay una mejor forma de hacerlas"

PD. Estas pidiendo ayuda y a todos los estas bateando a lo masacre.

nuk3zito 05-12-2008 18:49:47

Cita:

Empezado por Kipow (Mensaje 329905)
"Siempre hay mas de 1 forma de hacer las cosas y siempre hay una mejor forma de hacerlas"

PD. Estas pidiendo ayuda y a todos los estas bateando a lo masacre.

Es cierto... lo que pasa es que necesito una solución a un problema específico. No pretendo darle la vuelta a ese problema, no es mi estilo.

Sorry, se que a algunos les molesta pero me pagan por esto (y ahora que lo pienso, si no les comparto mi sueldo, creo que es injusto que me den una solución).

Esa es mi postura, sorry. Me exigen solución a ese problema en especial y esa solución es la que busco.

Gracias por comprender.

egostar 05-12-2008 18:52:26

Cita:

Empezado por nuk3zito (Mensaje 329904)
Soy malo para decir sarcasmos (a un lenguaje, por Dios) por este medio.
Entonces si no está ausente, no está funcionando como debe ser. ;)

P.D. El vendedor estrella de Delphi Studio en México me dijo alguna vez: No creas todo lo que dice la cajita.
A lo cual el mismo en esas sesiones se dio cuenta que su comentario no le daba más valor a su producto si no que también abarcaba los bugs no mencionados.

Saludos.

Los sarcasmos se dicen cuando se deben decir y hasta para eso hay que tener estilo, y te reitero, habar de bugs requiere de cierto respeto y menos jactancia, un bug es esto

Cita:

Un defecto de software (computer bug en inglés), es el resultado de un fallo o deficiencia durante el proceso de creación de programas de ordenador o computadora (software). Dicho fallo puede presentarse en cualquiera de las etapas del ciclo de vida del software aunque los más evidentes se dan en la etapa de desarrollo y programación. Los errores pueden suceder en cualquier etapa de la creación de software
Pero cuando no existe algo no es que no funcione como debe de ser, simplemente no existe, pero por fortuna siempre hay personas que en lugar de llorar por la ausencia de ese algo dedican mucho tiempo a solucionar el problema, cosa que está sustentada en el link que te proporcioné.

Yo no se porque el comentario ironico que haces sobre ese "vendedor estrella", en fin, parece que sigues tomando las cosas muy a pecho.

Ni modo, asi es esto.

nuk3zito 05-12-2008 19:01:52

Te digo que soy malo para los sarcasmos y en este caso lo del vendedor estrella no era un sarcasmo.
Mira, veámoslo de esta manera... no se trata de reprogramar todo ¿crees que el problema específico de memoria pueda ser solucionado? (esto como lo dije antes, no depende realmente de la memoria física de la PC.

Quiero aclarar que Delphi me gusta demasiado, más que cualquier otro lenguaje, pero estoy consciente de que pueda tener bugs (y vaya que los ha tenido). Pero hasta no saber si este es bug o no, no puedo retirarme de la solución.

Saludos egostar.

P.D. Espero no estarme haciendo acreedor a un baneo... espero no estar violando guías de estilo o cosas así. Eso será aceptado si alguien me llama la atención

nuk3zito 05-12-2008 19:06:29

Hono a quien honor merece
 
Egostar, ese artículo de codegear me sirve bastante, me dio algunas ideas.

Gracias.

Cita:

Empezado por egostar (Mensaje 329902)
:rolleyes::rolleyes::rolleyes:
Ya buscaste bien?

P.D. Esos son los aportes que se buscan... aunque admítanlo... disfrutan usar el sarcasmo para aportarlos, jijiji :p

Delphius 05-12-2008 19:55:30

Hola nuk3zito,
Antes que nada espero que no te molestes demasiado por mis palabras.

La verdad es que tener tanta cantidad de objetos no es muy común (sobre todo si se tiene en cuenta que al parecer sólo estamos hablando de un módulo) y creo que por más que unos 1300 objetos no ocupen demasiada memoria (en promedio 4 bytes [lo que "ocupa un objeto"] por 1300, no es taaanto), me parece que en forma general, sin conocer con mayor profundidad como estás llevando a cabo todo el proceso y el código, que es un mal diseño.

No es por criticarte, pero es que a mi esa cifra me indica que hay un mal análisis y diseño. Creo que deberías replantear la posibilidad de que se analice el tema nuevamente.

Dices que obedeces ordenes, pero ¿no existe la posibilidad de que propongas una revisión?
Si hay problemas con la recolección de basura, es porque algo mal tienes. En algún punto de todo el código que tienes hay una falla; no es por desacreditarte... somos humanos. Nos podemos equivocar.

Quizá es un error tonto y se te pasó. Suele pasar, a mi pasa. Puede pasarte a ti, en vez de apresurarte a dictaminar que es un bug ¿porqué no revisas el código y le haces una traza?

Trantandose de algo que posiblemente sea algo grande. Lo mejor es llevar un buen proceso de control, un plan de pruebas.

Sólo me voy a tomar la libertad de hacer una simple pregunta ¿Es muy estrictamente necesario tener 1300 objetos?

Tal vez me digas: no hay tiempo, se necesita para ahora, que no se vale retocar todo. Lamentablemente esta es una situación en la que muy posiblemente debas retocar muchas cosas. Un Out of memory no sale por arte de magia y en verdad para que salga algo mal hay que hacer.


No te digo que tu hayas mal programado. No te culpo a ti, sino que te hago saber que ante situaciones como éstas es mejor ser más precavido, más abierto, analizar más y recién codificar. Tal vez se pierda más tiempo pero esto a la larga puede hacerte ganar tiempo.

No más esa es mi opinión, y como cualquier otra, está sujeta a la voluntad de cada quien en ignorarla, aceptarla, escucharla, compartirla y/o rechazarla.

Saludos,

cHackAll 05-12-2008 20:08:39

Cita:

Empezado por Delphius (Mensaje 329922)
...y creo que por más que unos 1300 objetos no ocupen demasiada memoria (en promedio 4 bytes [lo que "ocupa un objeto"] por 1300, no es taaanto)...

:eek: explicate!

Delphius 05-12-2008 20:15:31

Cita:

Empezado por cHackAll (Mensaje 329927)
:eek: explicate!

Hola Javier,
¿Que no es que es eso lo que ocupa la variable que apunta al objeto?;)

Se que no es una medida tan fiable y exacta de lo que ocupa realmente un objeto, pero al menos 4 bytes por los 1300 nos da 5200 bytes. Y bueno... de allí ya podemos empezar a hacer algunas cuentas de lo que se está "consumiendo".

Saludos,

nuk3zito 05-12-2008 20:18:13

Saludos Delphius,
He visto puros famosos por aquí, me da gusto.

Cita:

Empezado por Delphius (Mensaje 329922)
Sólo me voy a tomar la libertad de hacer una simple pregunta ¿Es muy estrictamente necesario tener 1300 objetos?

La cantidad de objetos la dicta la cantidad de registros que tiene una tabla. Un objeto por cada elemento de reporte. Cada elemento es la suma de cuentas o una fórmula interna que se tiene para calcular un valor.

Mira, te cuento la idea principal. El reporteador usa Excel como complemento, y lo que pasa es que se requiere proteger en gran medida los datos y la manera en que estos se calculan y a excel solo se le deja la tarea de recibir nuestros valores. Lo que se nos ocurrió en su momento es solo enviar los valores a nuestra hoja de excel y listo... que él se encargue del otro asunto.
Ahora bien, siendo Delphi un lenguaje orientado a objetos, la idea aquí es que cada elemento se manejara por si solo (quize probar ese poder), que cada elemento tuviera sus propios métodos y propiedades.
Como tu bien dices, nadie está excento de errores y creo que el mío puede estar al momento de liberar la memoria con el "free" (mi no basta experiencia con esto me hace dudar que el free libere de manera correcta el objeto)

Cita:

Empezado por Delphius (Mensaje 329922)
en promedio 4 bytes [lo que "ocupa un objeto"]

Con esto supongo que te refieres a la referencia a un objeto, pero una instancia de un objeto ocupará tantos bytes compongan sus miembros. De todos modos dejemos esto a un lado, lo que realmente importa es que aunque cada instancia pesara 1Kb esto multiplicado por 1300 (que es el numero de elementos de mi reporte) se me sigue haciendo poco, así que en este grado solo estoy buscando cual fue mi error, en cual línea de código está.

Cita:

Empezado por Delphius (Mensaje 329922)
Hola nuk3zito,
Tal vez me digas: no hay tiempo, se necesita para ahora, que no se vale retocar todo. Lamentablemente esta es una situación en la que muy posiblemente debas retocar muchas cosas. Un Out of memory no sale por arte de magia y en verdad para que salga algo mal hay que hacer.

Se que esos errores no se dan solos y no salen por arte de magia, creeme... esto ya es más un reto personal, puesto que la solución al problema la tengo en rediseño (no usar objetos?) pero ya es más necesidad personal descubrir el motivo de este error lejos de rediseñar todo. No se si me explico.

Agradezco como no tienes idea cualquier aporte de los foristas.

Delphius 05-12-2008 20:31:58

Cita:

Empezado por nuk3zito (Mensaje 329931)
He visto puros famosos por aquí, me da gusto.

¿Famoso? ¿Donde?
El día que yo sea famoso va a estallar el mundo debido que mi ego va a ocupar todo el planeta.
No más es que me tomo el tiempo aquí. De famoso no tengo nada, excepto el ser un loco trastornado.


Cita:

Empezado por nuk3zito (Mensaje 329931)
Agradezco como no tienes ideas cualquier aporte de los foristas.

Antes de ponerme los guantes, debido a una mala interpretación de tus palabras, quiero preguntarte ¿bajo que contexto debo entender cuando me dices "que no tengo ideas"?:confused:

No puedo distinguir si me estás insultando educadamente y me tome el raje, diciendome algo como "Si no tienes p.. idea vete a otro lado"; o por el contrario me lo dices debido a que no te he ofrecido alguna alternativa a tu diseño.

Por la forma en como está redactado tu mensaje, puede interpretarse de muchas maneras. De igual modo yo no fui lo suficientemente claro al explicar la cuestión de los 4 bytes.

Saludos,

nuk3zito 05-12-2008 20:37:28

DISCULPAME!!!

Realmente se me fue una "s" de más...

Entiendo tu reacción tal como se ha desencadenado el hilo. Sorry en verdad.

Una letrita puede cambiar todo el sentido de una frase.

Cita:

Empezado por Delphius (Mensaje 329936)
Antes de ponerme los guantes, debido a una mala interpretación de tus palabras, quiero preguntarte ¿bajo que contexto debo entender cuando me dices "que no tengo ideas"?:confused:

No puedo distinguir si me estás insultando educadamente y me tome el raje, diciendome algo como "Si no tienes p.. idea vete a otro lado"; o por el contrario me lo dices debido a que no te he ofrecido alguna alternativa a tu diseño.

Por la forma en como está redactado tu mensaje, puede interpretarse de muchas maneras. De igual modo yo no fui lo suficientemente claro al explicar la cuestión de los 4 bytes.

Saludos,


Delphius 05-12-2008 20:52:40

Bueno, ideas... ummm puedo maquinar algunas cuantas en cuestión de algunas horas.

Se que te puede sonar muy parecida mi idea, pero.... ¿Porqué no un TStringGrid?

La cuestión es que prefiero tirarte una serie de interrogantes para que tu mismo juzgues tu diseño y puedas encontrar ya sea una nueva alternativa o en su defecto, los puntos débiles del diseño.

1. ¿Que tan particular es un panel respecto a otro? ¿Son muy particulares? No comparten algo en común, fuera de una cuestión de que responde a una misma clase, y por tanto tienen las mismas características. A lo que voy es es a esta pregunta fundamental: ¿Que hace único a un panel, botón, o sea el control que sea?

2. Relacionado con el anterior, como corolario, ¿Existe algún tratamiento común a todos?

3. ¿Quien crea a quién? ¿Quien borra a quién? ¿Quién es dueño de quién? En fin cualquier pregunta que te permita establecer el grado de pertenencia y relación entre los objetos. En pocas delimitar claramente el alcance de cada clase y el ciclo de vida que le corresponde.

4. ¿Hasta que punto se hace empleo de métodos genéricos? ¿Son muy particulares? ¿Son virtuales? ¿Que tan amplia es la jerarquía de clases? ¿Es congruente la representación "física" del reporte con el tamaño del diseño de las clases?

Por ahora se me ocurren estas preguntas, puede que más adelante surjan otras.

Saludos,

Lepe 05-12-2008 21:41:58

Cambia tu bucle por este otro:
Código Delphi [-]
  for i := slElementos.Count - 1 downto 0
    if Assigned( slElementos.Objects[i] ) then
    begin
       slElementos.Objects[i]).Free;
    end;
  slElementos.Clear;

El bucle que haces era en orden ascendente, pero cuando eliminas uno, el Count cambia, por lo que siempre que eliminas uno, te saltas otro....ejemplito:

tienes en el stringlist:
Código:

cero
uno
dos
tres

empezamos el bucle y borras el elemento cero, la lista pasa a ser:
Código:

uno
dos
tres

ahora pasa a borrar el índice uno....que borraría el elemento "dos":
Código:

uno
tres

Ahora pasaríamos a borrar el índice 3, pero como no existe (la propiedad count se ha actualizado al nuevo valor, pues sale del bucle.

Peor aún, no se termina de eliminar los elementos del stringlist, no ya los objetos en sí mismo, sino las cadenas de texto que tengas.

Como norma general: al destruir elementos de cualquier tipo de array o lista, hazlo siempre en orden descendente.

Con mi modificación no haría falta utilizar un bucle descendente, ya que no elimino el "string", pero para recordar este tipo de fallos, siempre lo hago.
¿Por qué no hago el "Delete(i)"? Por que es más eficiente borrarlos todos de un golpe con Clear, que ir borrándolos uno a uno. Si no necesitas borrarlos todos, pone el delete(i) dentro del bucle, ahora no fallará.

Como ves Delphi aquí no tiene nada que ver, primero tenemos que reconocer que somos novatos, para aceptar este tipo de fallos y aprender de ellos, es la única forma de llegar a ser algún día... por ejemplo cómo cHackAll ;)

Como ya dije, no estoy de acuerdo con crear 1300 botones, pero si ha de hacerse...se hace. Hacerlo "pa ná" es tontería ;)

Saludos.

nuk3zito 05-12-2008 21:47:15

Gracias Lepe,
Realmente este es el codigo que tengo.

Por querer maquillarlo puse ese Delete() por error.


Código Delphi [-]
procedure TFControlReportesExcel.LimpiarListaElementos;
var
   i: integer;
begin
   Self.PonerMsgEspera('Eliminando elementos...');
   try
      try
         for i := 0 to slElementos.Count - 1 do
           if Assigned( slElementos.Objects[i] ) then
              if slElementos.Objects[i] is TObjElemento then
              begin
                 if slElementos.Objects[i] is TObjTitulo then
                    begin
                       TObjTitulo(slElementos.Objects[i]).Free;
                    end
                 else if slElementos.Objects[i] is TObjFormulaExcel then
                    begin
                       TObjFormulaExcel(slElementos.Objects[i]).Free;
                    end
                 else if slElementos.Objects[i] is TObjConcepto then
                    begin
                       TObjConcepto(slElementos.Objects[i]).Free;
                    end;
      //           slElementos.Delete(i);
              end;
      except
      end;
   finally
      slElementos.Clear;
      Self.QuitarMsgEspera();
   end;

   panGuias.Width:= ScrollBox1.Width + SIZEX;
   panGuias.Height:= ScrollBox1.Height + SIZEY;
   panDesign.Width:= ScrollBox1.Width;
   panDesign.Height:= ScrollBox1.Height;
end;

La primera vez si tenia un Delete() (hace como un mes), pero ese fue corregido en la misma hora.... lo dejé comentarizado

Lepe 05-12-2008 22:09:28

Código Delphi [-]
procedure TFControlReportesExcel.LimpiarListaElementos;
var
   i: integer;
   strClass :string;
begin
   Self.PonerMsgEspera('Eliminando elementos...');
   try
     try
     for i := 0 to slElementos.Count - 1 do
       if Assigned( slElementos.Objects[i] ) then
       begin
         strClass := sElementos.Objects[i].ClassName;
         slElementos.Objects[i]).Free;
       end;
    except 
        ShowMessage('error al liberar el '+ strClass');
    end;
   finally
      slElementos.Clear;
      Self.QuitarMsgEspera();
   end;
   panGuias.Width:= ScrollBox1.Width + SIZEX;
   panGuias.Height:= ScrollBox1.Height + SIZEY;
   panDesign.Width:= ScrollBox1.Width;
   panDesign.Height:= ScrollBox1.Height;
end;
1º- Si en un except no haces nada, estás ocultando esa excepción, por tanto jamás encontrarás el fallo que hay en esa rutina. Entiendo que estando desesperado o simplemente apresurado, lo hayas puesto.

2º- ¿para qué está el polimorfismo en delphi? pues a usarlo. Todos las clases heredan de TObject en delphi, pero si llamamos a Tobject.Free, delphi sabrá que ese objeto es en realidad un TobjTitulo o lo que sea, por tanto, ejecutará el TobjTitulo.Free o el destructor que le corresponda.

3º- Ese bucle está bien, por tanto, olvida ese código y pasa a mirar si en algún momento estás liberando alguno de esos objetos. Por último pasa por mirar el método destroy de cada uno de tus clases: TobjTitulo, TobjFormulaExcel, etc porque ahí estará el error. De hecho he modificado el código para que salte un ShowMessage en la clase que te da el error al liberarlo de memoria, creo eso te ayudará a localizar el error.

Si sale el error antes que el ShowMessage, es precisamente porque objects[i] tiene un puntero no válido, es decir, es distinto de nil, pero apunta a una zona de memoria que ya se liberó, ataca por ahí.

Saludos

nuk3zito 05-12-2008 22:19:59

Gracias Lepe por tomarte el tiempo de modificar el código.

Cita:

Empezado por Lepe (Mensaje 329950)
1º- Si en un except no haces nada, estás ocultando esa excepción, por tanto jamás encontrarás el fallo que hay en esa rutina. Entiendo que estando desesperado o simplemente apresurado, lo hayas puesto.

Realmente ese except fue herencia del programador, pero tienes toda la razón, no tiene cas ponerlo o debería haber enviado el mensaje de error que presentara en pantalla

Cita:

Empezado por Lepe (Mensaje 329950)
2º- ¿para qué está el polimorfismo en delphi? pues a usarlo. Todos las instancias heredan de TObject en delphi, pero si llamamos a Tobject.Free, delphi sabrá que ese objeto es en realidad un TobjTitulo o lo que sea, por tanto, ejecutará el TobjTitulo.Free o el destructor que le corresponda.

No use TObject.Free por simple ignorancia, pensando que el Free debería dispararse desde su máximo nivel de herencia. Cada día aprendo más.

Cita:

Empezado por Lepe (Mensaje 329950)
3º- Ese bucle está bien, por tanto, olvida ese código y pasa a mirar si en algún momento estás liberando alguno de esos objetos. Por último pasa por mirar el método destroy de cada uno de tus clases: TobjTitulo, TobjFormulaExcel, etc porque ahí estará el error. De hecho he modificado el código para que salte un ShowMessage en la clase que te da el error al liberarlo de memoria, creo eso te ayudará a localizar el error.

Voy a probar este código que me envías y te lo informo (estoy trabajando ya en ello)

Que bueno que me mencionas que revise los métodos destroy... ahora están vacíos pero existen (porque antes tenían código), los voy a eliminar puesto que no hay nada que liberar ya de manera explícita.
Se que el error está en una simple línea seguramente, gracias nuevamente.

nuk3zito 08-12-2008 22:07:20

Solucionado!!!?
 
Buenas tardes,
Referente a este penoso problema les comento que todos y ninguno tuvo la razón. Algunos de los comentarios fueron muy atinados (la mayoría de hecho) para resolver el problema según lo que parecía que podría ser la causa, sin embargo, me he dado cuenta que este problema no se me está presentando en otras computadoras con Windows XP (yo utilizo Vista Bussines) y en Vista dejó de presentarse cuando eliminé los ìconos que se mostraban en los botones (los tomaba de un ImageList)... al menos en mi laptop esto pasaba.
Como mencioné al inicio del post... usaba los TJvXPButton pero en el título del post mencioné TBitBtn para dar a entender con esto que no importaba realmente el componente desde donde heredaba... la realidad es que si importaba mucho, ya que con los TBitBtn's se presentaba ese problema en menor escala que con los TJvXPButton, pero aún así se presentaba en ambos casos.
El problema radicalmente dejó de presentarse cuando eliminé las imágenes de los botones.

Solución: Necesito revisar y reinstalar mi laptop... y temporalmente quitar las imágenes de los botones. TODO EL PROBLEMA ES LO VISUAL según he visto, ya que sin estar creando o eliminando objetos el problema se presentaba al estar "refrescando" explícita o implícitamente la pantalla (principalmente al hacer algún scroll).

Más bien es veredicto, ya que probando este mismo módulo en PC's con Windows Vista si se llegó a presentar el problema (aunque con menor frecuencia que en mi laptop) aunque en la computadora tuviera 256 Mb de memoria y otra característica común es que al hacer un scroll en el panel contenedor este tardaba muchísimo en hacer todo su trabajo (dibujar los botones).

Debo darle la vuelta al menos a estos componentes visuales tan bonitos (TJvXPButton) ya que a Windows Vista le vale churro si se ven bonitos o no... él busca siempre aplicar sus propiedades a lo que se deje.

Nuevamente agradezco todos sus comentarios aunque algunos no sean del agrado de todos, de cualquier mensaje siempre se logra obtener algo positivo.

Saludos a todos.


La franja horaria es GMT +2. Ahora son las 01:30:37.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi