Ir al contenido


Foto

Crear botones en runtime que cubran el formulario


  • Por favor identifícate para responder
15 respuestas en este tema

#1 FGarcia

FGarcia

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 687 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 07:04

Saludos!!

Hace rato que no circulaba por aqui, bastante trabajo afortunadamente (lastima de remuneracion  : )

Jeje bueno a llorar a otra parte, resulta que tengo unas PC "Todo en Uno" con monitor de tipo touch, estan instaladas en un area de trabajo bastante sucia y humeda por lo que en ocasiones falla el "touch" despues de limpiarlas quedan listas para trabajar (una limpieza con paño humedo y ya......pero a mucha gente se le hace eso como si fuese un castigo  :( y ademas insisten en decir que no funciona ) asi que se me ocurrio que despues de limpiarlas les pueda comprobar que todo el touch funciona correctamente, ¿como? con un programita que cubra toda la pantalla de botones con la leyenda ¡pulsame!

He creado:
  Un formulario con un botón creado en tiempo de diseño el cual al ser pulsado deberá de crear botones  que cubran todo el formulario. Hasta el momento mis pruebas han sido solo una columna y una fila (un código malisimo  :s  )



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3. btnBoton: TButton;
  4. i, j, cuentaY, cuentaX, PosX, PosY: integer;
  5. begin
  6.   //Deshabilitamos el boton para evitar errores
  7.   Button1.Enabled := False;
  8.   //Escribo el titulo mas las dimensiones alto, ancho
  9.   Form1.Caption := Form1.Caption + ' Y: ' + IntToStr(Form1.Height) + ' X: ' + IntToStr(Form1.Width );
  10.  
  11.   //Inicializamos el contador de botones en Y
  12.   cuentaY := form1.Height div Button1.Height;
  13.   //Restamos el boton ya creado
  14.   CuentaY := CuentaY - 1;
  15.  
  16.   //Inicializamos el contador de botones en X
  17.   cuentaX := form1.width div Button1.Width;
  18.   //Restamos el boton ya creado
  19.   cuentaX := CuentaX - 1;
  20.  
  21.   //Definimos la posicion top del boton a crear
  22.   PosY := Button1.Top;
  23.   //Creamos el boton
  24.   for i := 0 to cuentaY do
  25.       begin
  26.         btnBoton := TButton.create(self);
  27.         //Asignamos propiedades
  28.         with btnBoton do
  29.             begin
  30.               Parent := self;
  31.               Left := 0;
  32.               Top := PosY + Button1.Height ;
  33.               Height := Button1.Height ;
  34.               Width := Button1.Width ;
  35.               Name := 'Boton' + IntToStr(i);
  36.               Caption := '¡Pulsame ' + IntToStr(i) +'!';
  37.               Color := clDefault;
  38.               Visible := True;
  39.               PosY := PosY + Height;
  40.             end;
  41.       end;
  42.  
  43.   //Definimos la posicion left del boton a crear
  44.   PosX := Button1.Left;
  45.   //Creamos el boton
  46.   for i := 0 to cuentaX do
  47.       begin
  48.         btnBoton := TButton.create(self);
  49.         //Asignamos propiedades
  50.         with btnBoton do
  51.             begin
  52.               Parent := self;
  53.               Left := PosX + Button1.Width ;
  54.               Top := 0 ;
  55.               Height := Button1.Height ;
  56.               Width := Button1.Width ;
  57.               Name := 'BotonX' + IntToStr(i);
  58.               Caption := '¡Pulsame ' + IntToStr(i) +'!';
  59.               Color := clDefault;
  60.               Visible := True;
  61.               PosX := PosX + Width;
  62.             end;
  63.       end;
  64.  
  65. end;


¿Pueden ayudarme a hacer un código mas decente y ademas que cumpla el cometido de llenar toda el área del form?


Agradesco su tiempo!  (b)  (b)  (b)
  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 08:30

Que tal amigo Fidel,

A ver que te parece esto.

pulsame.jpg

Éste es el código:


delphi
  1. procedure TForm1.FormShow(Sender: TObject);
  2. var
  3.   I: Integer;
  4. begin
  5.   Alto := Height;
  6.   Ancho := Width;
  7.   for I := 1 to 108  do
  8.   begin
  9.     Boton := TBitBtn.Create(nil);
  10.     Boton.Parent := FlowPanel1;
  11.     Boton.Name := Format('Boton%d',[I]);
  12.     Boton.Height := Alto div 5 ;
  13.     Boton.Width := Ancho div 5 ;
  14.     Boton.Caption := '¡pulsame!';
  15.   end;
  16. end;


Saludos

Archivos adjuntos


  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 08:36

Digo, con tiempo se puede hacer algo más decente, pero ahí está la idea :)

Viva el FlowPanel :D :D :D

Saludos

PD: Necesitas Delphi 2006 o mayor  *-)


  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 09:33

Eliseo, ¿que tiene de interesante el TFlowPanel por sobre el TPanel común de toda la vida?

Saludos,
  • 0

#5 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 09:35

Eliseo, ¿que tiene de interesante el TFlowPanel por sobre el TPanel común de toda la vida?

Saludos,


Ahhh, pues porque no te interesa donde colocar los botones, los creas y se ordenan automáticamente ;)

Saludos
  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 09:50

Ahhh, pues porque no te interesa donde colocar los botones, los creas y se ordenan automáticamente ;)

Saludos

No jodas  :o ¿Y sirve para todos tipos de controles? De ser así, se la han currado.

Saludos,
  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 09:56


Ahhh, pues porque no te interesa donde colocar los botones, los creas y se ordenan automáticamente ;)

Saludos

No jodas  :o ¿Y sirve para todos tipos de controles? De ser así, se la han currado.

Saludos,


Así es, cualquier control que coloques se ordena dentro del FlowPanel.

Saludos
  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 10:42

Vaya... si que se la jugaron con ese componente.

FGarcia se puede mejorar tu código, vas bien. Yo le hago algunos cambios:

1) Si sabemos el Largo y Alto del control tanto del control como del panel/formulario podemos saber la cantidad a distribuir:


delphi
  1. CantidadX := LargoTotal div LargoControl;
  2. CantidadY := AltoTotal div AltoControl;


Entonces la cantidad total de controles será de:


delphi
  1. CantidaTotal := CantidadX * CantidadY;


Ahora, en realidad se puede saber la posición de todos y cada uno de los controles. Podemos aprovechar la matemática a nuestro favor. Para ilustrarlo, imaginemos que el form o panel es una matriz, para el ejemplo tenemos para distribuir (5 x 3):

0 - 1 - 2 - 3 - 4
5 - 6- 7 - 8- 9
10 - 11 - 12 - 13 - 14

Nota que utilicé una notación basada en cero. Ya verás porqué. Ahora, observemos como sería colocados en base a sus coordenadas:

0 = (0,0) ... 4 = (4L, 0)
5 = (0, 1A) ... 9 = (4L, 1A)
10 = (0, 2A) ... 14 = (4L, 2A)

Siendo L el LargoControl, y A el AltoControl. Fíjate que en realidad cualquier control estará ubicado en un múltiplo (Mx * L, My * A) Para la primera fila (fila 0) Mx va de 0 a 4, y vuelve a repetirse la secuencia para la segunda y tercer fila. My por otra parte, incrementa su valor en cada paso de de fila (0 a 2).

Entonces tenemos que, si contamos desde cero:


delphi
  1. My := -1; // inicialmente no hemos posicionado nada....
  2. for i := 0 to CantidadTotal - 1 do
  3. begin
  4.   Control := TButton.Create(nil);
  5.   Control.Name := 'Pulsame' + IntToStr(i);
  6.   // aquí vamos a posicionarlo:
  7.   Mx := i MOD CantidadX;
  8.   if Mx = 0
  9.     then Inc(My); // hemos iniciado una nueva fila
  10.   PosX := Mx * LargoControl;
  11.   PosY := My * AltoControl;
  12.   Control.Width := LargoControl;
  13.   Control.Heigh := AltoControl;
  14.   Control.Left := PosX;
  15.   Conttol.Top := PosY;
  16. end;


Fíjate que no hace falta hacer dos ciclos... podemos crear y posicionarlos de una.  ;)

Espero que esto te sea de orientación.
  • 0

#9 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 25 abril 2012 - 08:28

Para algo decia yo que debia usar Alto y Ancho, pero francamente no tenía la mente como para forzarla más, ya no estoy en edad de esos menesteres y menos a esas altas horas del día.

A veces me gustaría tener 25 años menos :D :D :D

Saludos
  • 0

#10 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 25 abril 2012 - 07:03

Para algo decia yo que debia usar Alto y Ancho, pero francamente no tenía la mente como para forzarla más, ya no estoy en edad de esos menesteres y menos a esas altas horas del día.

A veces me gustaría tener 25 años menos :D :D :D

Saludos

No te creas que me resultó fácil a mi tampoco. Tenía la idea en la punta de la lengua como se dice, pero no encontraba la forma de expresarlo. Tuve que darme unos minutos y bueno al fin me salió "eso".
Allí se fue la última neurona que me quedaba anoche, lo siguiente fue apagar la computadora e ir a dormir  :D

Y a mi me gustaría tener 7 años menos... ¡como no existe RollBack!  *-)

Saludos,
  • 0

#11 FGarcia

FGarcia

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 687 mensajes
  • LocationMéxico

Escrito 26 abril 2012 - 08:45

Hola!

No crean que me he olvidado de esto pero eso de andar fuera de la oficina todo el dia no me ha permitido poner en marcha esto y comentar los resultados.

Eliseo, si he visto algunos de los controles nuevo en D2010, sin embargo en los últimos meses he estado "jugando" con aparatos nuevos y algunos de ellos con programación tan básica que he optado ir a las bases de la programación para mejorar y entender mis habilidades.

Marcelo, andaba en muy el fondo de mi pequeña y blanca cabezita la idea del eje cartesiano pero no lo llegue a concretar muy bien, bastante explicito tu desarrollo.

Pruebo y les comento que resulto.

La única neurona que me queda la uso para respirar asi que aun tengo que enseñarle a trabajar con tiempos compartidos de procesador, imagínense es del mismo modelo que la de Eliseo!!!




(b) (b) (b) (b) (b) (b)
  • 0

#12 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 26 abril 2012 - 09:51

Pruebo y les comento que resulto.


Esperamos tus comentarios (y)

La única neurona que me queda la uso para respirar asi que aun tengo que enseñarle a trabajar con tiempos compartidos de procesador, imagínense es del mismo modelo que la de Eliseo!!!


Tómalo con calma mi amigo que puede sufrir un sobrecalentamiento y se va a resetear, caray, llega la edad en que uno debe aceptarlo y decir, Viva la Paz!!!  :D :D :D

Saludos
  • 0

#13 FGarcia

FGarcia

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 687 mensajes
  • LocationMéxico

Escrito 26 abril 2012 - 10:47

Pues les anexo la imagen resultante, ¡vaya que trabaja el cpu mientras crea los "botoncitos"!

De esto sale una pregunta que comentare en otro hilo para no mezclar temas. Al final cree el form y coloque un Timer que ejecutara el procedimiento de crear los botones; esto fue porque queria que el Form apareciese maximizado y ahi se genero la duda que menciono.

Saludos!!



delphi
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3. Control: TButton;
  4. Mx, My, PosX, PosY, i:integer;
  5. begin
  6.   Timer1.Enabled := false;
  7.  
  8.   CantidadX := Width div 78; // LargoTotal div LargoControl;
  9.   CantidadY := Height  div 25; //AltoTotal div AltoControl;
  10.   CantidadTotal := CantidadX * CantidadY;
  11.  
  12.   My := -1; // inicialmente no hemos posicionado nada....
  13.   for i := 0 to CantidadTotal - 1 do
  14.       begin
  15.           Control := TButton.Create(nil);
  16.           Control.Name := 'Pulsame' + IntToStr(i);
  17.           //Quien es el padre del control
  18.           Control.Parent := Self;
  19.  
  20.           // aquí vamos a posicionarlo:
  21.           Mx := i MOD CantidadX;
  22.  
  23.           if Mx = 0 then
  24.               Inc(My); // hemos iniciado una nueva fila
  25.  
  26.           PosX := Mx * 78; //LargoControl;
  27.           PosY := My * 25; //AltoControl;
  28.  
  29.           Control.Width := 78; //LargoControl;
  30.           Control.Height := 25; //AltoControl;
  31.           Control.Left := PosX;
  32.           Control.Top := PosY;
  33.       end;
  34.  
  35. end;



P.D. Si observan esto lo hice en Lazarus 0.9.31 (CodeThyphon 2.50)

Archivos adjuntos


  • 0

#14 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 27 abril 2012 - 09:19

Vaya... ese si que es un tablero  :D

Por el consumo de CPU pues si... puede ser elevado, sobre todos si los botones son muy chicos.
Quizá sea conveniente hacer dos cosas:
1) usar DoubleBuffered
2) forzar un Application.ProcessMessages al final de cada fila.

Eso podría ayudar en algo.

Además hay que tener en cuenta de que cada botón necesita de recursos, lo que se traduce en más Handles y es un motivo por el que se consume más memoria.

Lo de utilizar un timer no se si es bueno o no. Dependerá más que nada de diseño del sistema.

Saludos,
  • 0

#15 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 27 abril 2012 - 09:36

Pues usando Hilos minimiza un poco el consumo.

Saludos.
  • 0

#16 FGarcia

FGarcia

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 687 mensajes
  • LocationMéxico

Escrito 27 abril 2012 - 11:21

Hola!

Pues la aplicacion solo es para probar (test) que realmente funciona todo el area de la pantalla touch, vaya una herramienta de diagnostico, no es como para meterse a tanto problema con los hilos y desempeño del cpu solo era una observacion.

En otro hilo Hector Randolph hace este comentario sobre como asignar un evento por codigo :

Bueno, aunque no aclaras muy bien qué problema se te presenta, voy a suponer que estamos hablando de Lazarus.

En tal caso, para asignar un evento por código se hace de la siguiente manera.



delphi
  1.   OnMouseDown:= @ControlMouseDown();
  2.   OnMouseMove:= @ControlMouseMove();
  3.   OnMouseUp:= @ControlMouseUp();




Saludos


Bueno pues lo hice durante la creacion del control (Boton)



delphi
  1. //Asignamos el evento al boton creado
  2.           Control.OnClick := @EliminaBoton;  //Delphi solo: EliminaBoton;



si coloco los parentesis vacios me genera un error de que esperaba el ";" y recibio un "(" aqui no se si eso es una actualizacion del modo de asignacion o que, si alguien sabe y nos lo comenta se agradece.

El codigo del procedimiento EliminaBoton es:



delphi
  1. procedure TForm1.EliminaBoton(Sender:TObject);
  2. begin
  3.   {if assigned(TButton(Sender)) then
  4.     TButton(Sender).Free ;  }
  5.   showmessage(TButton(Sender).Caption);
  6. end;



El codigo comentado no me funciona

[Window Title]
Error

[Content]
El proyecto TestTouch ha lanzado una excepción de la clase 'External: SIGILL'.

At address 22DA0E9

[Aceptar]

:huh:  :huh:  :huh:

¿Que esta mal?


  • 0




IP.Board spam blocked by CleanTalk.