Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Crear en ejecucion varias instancias de un mismo grupo de elementos

Saludos a tod@s !

He estado buscando en el foro pero lo que he encontrado no me resuelve mis dudas.

Quiero crear en tiempo de ejecución 70 'fichas' iguales, cada una de las cuales contiene 4 Label's, 6 Shape's y 1 Image. Me gustaría considerarlo como un Array para posteriormente poder referenciar directamente por el índice en el array.

He pensado algo así como :

Código Delphi [-]
type
  TRackCard = Record
    LabelA : TLabel;
    LabelB : TLabel;
    LabelC : TLabel;
    LabelD : TLabel;
    ShapeA : TShape;
    ShapeB : TShape;
    ShapeC : TShape;
    ShapeD : TShape;
    ShapeE : TShape;
    ShapeF : TShape;
    ImageA : TImage;
  end;
 
  TForm = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    RackCard : Array of TRackCard;
  public
    { Public declarations }
  end;

  ...
 
procedure TForm.FormCreate(Sender: TObject);
begin
  ...
  SetLength(RackCard,70);
 
  for I := 0 to 69 do begin
 
    RackCard[i] := TRackCard.Create;
 
    RackCard[i].ShapeA.Left        :=    ...;
    RackCard[i].ShapeA.Top         :=    ...;
    // sigo definiendo aqui todos los demás atributos de ShapeA
    ...
    RackCard[i].ShapeB.Left        :=    ...;
    RackCard[i].ShapeB.Top         :=    ...;
    // sigo definiendo aqui todos los demás atributos de ShapeB, etcétera
    ...
  end;
 
end;
pero así no me funciona al parecer.

Como tengo que definir TRackCard ? Como Record, como TObject, como TObjectList ? Y como referirme correctamente a cada uno de los elementos de RackCard tales como ShapeA, ShapeB, etc ?

Gracias como siempre por vuestros consejos.

Saludos
__________________
Piensa siempre en positivo !
Responder Con Cita
  #2  
Antiguo 24-08-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Usar un Array debería funcionar, empero, son objetos los que contiene el "record" y estos han de ser creados antes de acceder a los mismos. Por otro lado usar un Array presentaría otros problemas, que desaparecerían si usaras algo como un "TObjectList".

Aunque a mí se me ocurre que puedas hacerlo de forma más o menos "visual", sobre todo si los controles de las "fichas" no variarán de ficha a ficha, es decir, nada te impide usar un formulario, donde situarías los controles que te fueran menester.

Y a partir de ahí a rehusar el formulario, es decir, a crear instancias del formulario "plantilla" y mostrar este cuando fuera oportuno. Eso también te quitaría dolores de cabeza a la hora de crear objetos y destruirlos. Tal vez alguien pueda aportar otras ideas.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #3  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Gracias David por responder.

Tengo ya el formulario totalmente operativo con mis 70 fichas, cada una de ellas con 11 elementos (entre Shape's, Label's, etc).

Además hay otros elementos adicionales en mi form. Lo que me lleva a tener más o menos 1000 (!!) elementos en mi formulario. Todos ellos creados en tiempo de diseño. Ahí no está el problema.

Lo que pasa es que para referirme a cada elemento de cada ficha y cambiarlo de la manera adecuada, lo hago por ejemplo de la siguiente manera :

Código Delphi [-]
(FindComponent('ShapeD'+Trim(Copy((Sender as TShape).Name,7,2))) as TShape).Visible := False;

y no veo como referirme a ellos si no es utilizando FindComponent.

Como ya se ha comentado en varias ocasiones en el Foro, FindComponent tiene que recorrer siempre toda la lista de componentes en el form para encontrar el adecuado.

Por eso intentaba optimizar el proceso y en vez de como ahora, teniéndolos creados en tiempo de diseño, crearlos mediante un Array y poder referenciar entonces directamente por el Array, con lo cual supongo (... que no lo sé, y por eso quería probar) mejoraría bastante la velocidad.

Y por eso pensé en crear un Array de 'fichas' a las cuales poder referirme directamente por su índice.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #4  
Antiguo 24-08-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Creo que no me expliqué bien respecto de la parte "visual" del asunto. Según yo lo veo cada ficha podría ser un componente, que contuviera a su vez los que fueran menester. Tal vez tendrías que fabricártelo tú mismo, y puede que no visualmente, pero, el caso es contar con un componente "ficha".

Luego podrías usar dicho componente en tiempo de diseño o en tiempo de ejecución. Y referirte a los subcomponentes de su interior no por separado, sino a través de su "ficha" contenedora. Tal vez incluso podrías implementar algún que otro método en el componente "ficha" que te echara una mano.

De este modo no se trataría ya de localizar un "Shape" entre los cientos que hay en las decenas de "fichas", si que se trataría de trabajar con las "fichas" más o menos directamente. Si luego además quieres añadir todas las "fichas" en un "TObjectList" (o un descendiente, de modo que pudieras añadir métodos y propiedades útiles al mismo) pues adelante.

Pero no me hagas mucho caso... intento aportar alguna idea... nada más. Lo mismo no me estoy enterando de nada.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #5  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Pues si, eso es precisamente lo que pretendía.

No sé si para ello debo de crear un nuevo 'componente'. Creo que no. Lo que quería precisamente era agrupar todos ellos en 'algo' que se llame 'ficha'. Eso se puede ? Yo pensaba que se podría con un Record (o algo así) (que se denominara 'Ficha') que a su vez 'contuviera' a los diferentes Label's y Shape's. Y después tener un array de 'fichas'. Eso pretendía explicar al principio de este hilo.

Lo que no sé es precisamente como codificar esa 'ficha' sin tener que crear como tal un 'componente' nuevo. No me parece oportuno utilizar para ello Frames, donde cada ficha fuera un frame.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #6  
Antiguo 24-08-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Es que depende... depende si lo quieres hacer en tiempo de diseño o en tiempo de ejecución. Creo que con lo de los "Frames" puedes haber dado en el clavo. De hecho, si estás haciéndolo en tiempo de diseño supongo que estarás usando algo así, porque no te imagino situando "cientos de Shapes" en un formulario... cada uno de su padre y de su madre.

Si cada ficha contiene unos controles ahí tenemos un componente, llámese "frame" o llámese otro que creemos nosotros. Pero eso es un componente que contiene unos determinados controles. Estoy contando, por otro lado, conque las fichas contienen los mismos controles, porque de otro modo el asunto se complicaría.

Pero aunque se complicara. Si existieran dos o tres tipos de fichas, todas serían un componente que tal vez pudiera heredar de una ficha "base". Y luego ver qué queremos hacer y cómo. Quiero decir que se me hace raro que quieras localizar el "Shape123", por ejemplo. Para mí que ahí falla algo...

Entiendo que deberías trabajar con las fichas, individualmente. Porque además no entiendo que quieras trabajar con un "Shape123", que sería como si dijéramos que las fichas no son en realidad componentes, y cada "Shape" puede estar en una ficha u otra aleatoriamente. No sé. Tengo la sensación de que me voy por las ramas, de que no estoy fino ni te estoy ayudando en nada... pero, ya está dicho.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #7  
Antiguo 24-08-2007
[basti] basti is offline
Miembro Premium
 
Registrado: ago 2004
Posts: 388
Poder: 20
basti Va por buen camino
Si lo que quieres es crear los componentes por código, como dice dec, tendrías que llamar al constructor de cada uno:

Código Delphi [-]
 
procedure TForm.FormCreate(Sender: TObject);
begin
  ...
  SetLength(RackCard,70);
 
  for I := 0 to 69 do begin
 
    // RackCard[i] := TRackCard.Create; // no hace falta, en los records no hay que llamar al constructor.
 
   // esto es lo nuevo
    RacCard[i].ShapeA := TShape.Create(self);
   // hasta aquí lo nuevo
    RackCard[i].ShapeA.Left        :=    ...;
    RackCard[i].ShapeA.Top         :=    ...;
    // sigo definiendo aqui todos los demás atributos de ShapeA
    ...
    RackCard[i].ShapeB.Left        :=    ...;
    RackCard[i].ShapeB.Top         :=    ...;
    // sigo definiendo aqui todos los demás atributos de ShapeB, etcétera
    ...
  end;
 
end;
__________________
Saludos.
Responder Con Cita
  #8  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Gracias Basti.

Funciona correctamente !

... de mi ! En otra parte del programa había hecho algo parecido y no me he percatado de ello para esta problemática que planteo en este hilo.

En cualquier caso, al código le falta un detalle para que funcione correctamente :
Código Delphi [-]
procedure TForm.FormCreate(Sender: TObject);
begin
  ...
  SetLength(RackCard,70);
 
  for I := 0 to 69 do begin
 
    RacKCard[i].ShapeA := TShape.Create(self);
    RackCard[i].ShapeA.Left        :=    ...;
    RackCard[i].ShapeA.Top         :=    ...;
    // sigo definiendo aqui todos los demás atributos de ShapeA
    RackCard[i].ShapeA. Parent := Self;
    ...
    RacKCard[i].ShapeB := TShape.Create(self);
    RackCard[i].ShapeB.Left        :=    ...;
    RackCard[i].ShapeB.Top         :=    ...;
    RacKCard[i].ShapeB.Parent := Self;
    ...
  end;
 
end;

Conclusión : He probado la funcionalidad de mi programa de esta manera, es decir, accediendo después directamente a RackCard[i].ShapeA (por ejemplo), en vez de utilizar el FindComponent en un Form que como ya comenté antes tiene cerca de 1000 elementos.

Cual sorpresa la mía. No hay NINGUNA mejora de rendimiento. Vamos, que lo mismo es acceder al Array directamente que utilizar FindComponent con una lista de 1000 componentes en el form.

En un procedimiento de actualización con datos y tal, ambos procesos tardan exactamente 4.6 segundos medidos en mi ordenador.

Por lo que concluyo que mi idea de utilizar arrays con acceso directo en vez de FindComponent finalmente no mejora el rendimiento. Así que se queda como está !

Gracias a todos por vuestra ayuda.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #9  
Antiguo 24-08-2007
[basti] basti is offline
Miembro Premium
 
Registrado: ago 2004
Posts: 388
Poder: 20
basti Va por buen camino
Me extraña que no haya diferencia entre uno y otro. He visto la implementación de FindComponent:
Código Delphi [-]
  if (AName <> '') and (FComponents <> nil) then
    for I := 0 to FComponents.Count - 1 do
    begin
      Result := FComponents[i];
      if SameText(Result.FName, AName) then Exit;
    end;
  Result := nil;

Es una búsqueda lineal, debería de tardar algún tiempo, mientras que el array es un acceso directo. Es posible que no exista diferencia por tratarse de un array dinámico.

Puedes probar a declararlo como
Código Delphi [-]
  RackCard : array [0..69] of TRackCard;

Y luego hacer la prueba dentro de un bucle de unas 100 repeticiones, para ver si realmente existe diferencia de tiempo.
__________________
Saludos.
Responder Con Cita
  #10  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Probablemente, por no decir casi seguro, pueda haber una diferencia de tiempo y de rendimiento entre las dos opciones que venimos comentando.

Lo que quiero aclarar es que a pesar de utilizar FindComponent con el número de componentes que tengo en mi form, el rendimiento no mejora en el procedimiento que realizo. He probado también declarando el Array como indicas arriba.

Trabajando con datos, y realizando las búsquedas que hago, actualizaciones, etcétera, (que está claro que es lo que más tiempo me va a llevar en cuanto a observar el rendimiento), no se aprecian diferencias entre ambas formas de implementación.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #11  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Siguiente duda que me surge :

Cuando selecciono cualquier elemento con el ratón, ya sea un Shape o Label del Record (RackCard) que acabo de crear (haciendo por ejemplo Click en cualquiera de ellos), como sé que posición en el array ocupa ??

Es decir, quiero saber cual ficha he seleccionado desde la 0 a la 69. La función IndexOf me devuelve el valor buscado ?

Nota: No puedo utilizar los Tag's de cada componente, debido a que ya los tengo asignados con otros valores.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #12  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Me acabo de dar cuenta que puedo utilizar la propiedad Name de cada elemento para saber cual he pulsado.

Si se os ocurre otra posibilidad ....
__________________
Piensa siempre en positivo !
Responder Con Cita
  #13  
Antiguo 24-08-2007
[basti] basti is offline
Miembro Premium
 
Registrado: ago 2004
Posts: 388
Poder: 20
basti Va por buen camino
Te iba a responder con lo de los Tag, pero ya veo que no es posible.

IndexOf no te dará el valor de la posición del array. Tendrías que hacer una función que hiciese el recorrido a través del array y compararlo con on el Sender que recibes en el OnClick.
__________________
Saludos.
Responder Con Cita
  #14  
Antiguo 24-08-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
¿Qué tal si usas el tag?

No, ya en serio, ¿qué tal si usas el tag? Ya sé que lo tienes asignado para otra cosa pero en realidad puedes usarlo para almacenar una referencia o puntero a un objeto o registro en donde almacenes lo que antes tenías en el tag y el índice que ocupa en el arreglo.

// Saludos
Responder Con Cita
  #15  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Si, ya sé que el Tag me pueda dar referencia a otro puntero.

Pero sería complicar más la cosa todavía.

Y por eso había pensado en el propio Name de cada componente. De hecho al asignarlo dinámicamente no le daba ningún nombre.

Si utilizo 'L' para Label's y 'S' para Shape's, junto con A, B, C, D, E o F según cada Label o Shape, junto con la posición dentro del propio Array RackCard, obtengo nombres tales como LA0, LA1 .., LA69 .... SA0, SA1, .., SA69 y simplemente preguntando por el nombre del Sender y haciendo un Copy y un StrToInt obtengo la posición.

Así me vale y creo que es más facil que complicar la cosa con el Tag que lo venía utilizando para otros valores.

__________________
Piensa siempre en positivo !
Responder Con Cita
  #16  
Antiguo 24-08-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por gluglu Ver Mensaje
Pero sería complicar más la cosa todavía.
Cuestión de puntos de vista. En mi opinión, usar arreglos y estructuras bien definidas, a la larga será mucho más claro y mantenible que estar usando trucos y cosas más propias de VB

// Saludos
Responder Con Cita
  #17  
Antiguo 24-08-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Cita:
y cosas más propias de VB


Pues en mi vida he tocado VB, así que seguro que por ahí no he adquirido esa 'mala' práctica.
__________________
Piensa siempre en positivo !

Última edición por gluglu fecha: 24-08-2007 a las 19:28:37.
Responder Con Cita
  #18  
Antiguo 24-08-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Bueno, bueno, a lo que me refiero, es a que- en mi opinión -no es una buena práctica basar el código en los nombre de los componentes. Eso es más propio de lenguajes interpretados. Y lo que puede parecer una complicación, a la larga redunda en un código más prolijo. Pero, como digo, es sólo mi opinión.

// Saludos
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Referencia a diferentes instancias del mismo Form gluglu OOP 14 23-02-2007 17:22:32
Evitar múltiples instancias de un mismo form Neomanar OOP 1 09-09-2005 17:10:26
Varias instancias DataModules rodmayes OOP 1 05-09-2005 13:37:45
Múltiples instancias de un mismo formulario Neomanar Varios 1 22-08-2005 15:20:29
Crear elementos en tiempo de ejecucion Tecnic2 OOP 12 15-06-2005 20:12:42


La franja horaria es GMT +2. Ahora son las 05:20:25.


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
Copyright 1996-2007 Club Delphi