Ir al contenido


Foto

como lanzar un menu vertical en Lazarus?


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

#21 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 01 enero 2016 - 01:59

Feliza año 2016 compañeros...

 

Como accedo a la propiedades de un TLabel que está dentro de un Tpanel? 

Me di cuenta que al tener un Tpanel e insertar en el un Timage, el texto del panel me resulta imposible alinearlo a la derecha, ya que si lo hago se pone por delante del icono, es decir: 

 

PANEL -> <icono> Texto; se lo alineo, lo que ocurre es que: Texto <icono>. Centré el texto, pero me di cuenta que los siguientes items del menu  hacia abajo se alineaba el texto centrado  como se aprecia en la imagen. Bueno, pues se me ocurrió poner un Tlabel al texto pero al pasar el ratón por el Tpanel me hace un cambio de color y el texto lo subraya, pero al pasar el ratón por el tlabel no hace nada, cuando lo que quiero es que hago lo mismo (cambiar de color y subrayado).

 

 

 

 

Archivos adjuntos


  • 0

#22 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 01 enero 2016 - 03:23

Como accedo a la propiedades de un TLabel que está dentro de un Tpanel? 

 

Dos formas:

 

1. Mantener una referencia al objeto label

2. Recorrer la propiedad Controls de tu Panel


delphi
  1. var
  2. I: Integer;
  3. LControl: TControl;
  4. for I := 0 to Panel.ControlCount -1 do
  5. begin
  6. LControl := Panel.Controls[I];
  7. if LControl is TLabel then
  8. end;


  • 0

#23 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 01 enero 2016 - 04:00

Hola Agustin Ortu, no pensaba que había que hacerlo así. De todos modos no entiendo el codigo, analizaré el codigo porque como digo en el tpanel

si lo tengo controlado:


php
  1. (Sender as Tpanel).Color:= clInactiveCaptionText; // Cambia a color rojo todo el panel al pasar por encima con el ratón.
  2. (Sender as Tpanel).Font.Style:=[fsUnderline]

 Luego creía que para el Tlabel, sería Tpanel.Tlabel.Font.Style o TPanel.TLabel(Sender).Color, pero veo que no tan sencillo.

 

Voy a desgranar este codigo que me suminitras Agustin y lo intento adaptar al caso, ya que desde luego solo dispongo de un TLabel dentro de un Panel.

 

Muchas gracias compañero!

 

Analizando la situación, el codigo que he realizado es este pero de "explota" al ejecutarlo dentro del begin, aun sin saber

si es correcto dichas sentencias:


php
  1. (Sender as Tpanel).Color:= clInactiveCaptionText; // Cambia al color dado todo el panel al pasar por encima con el ratón.
  2. (Sender as Tpanel).Font.Style:=[fsUnderline]; //el texto del tpanel lo subraya.
  3. for I:= 0 to (Sender as Tpanel).ControlCount -1 do
  4. LControl:=(Sender as Tpanel).Controls[I];
  5. if LControl is TLabel then
  6. begin
  7. (Sender as TLabel).Color:= clInactiveCaptionText; // cambiaría el color de label
  8. (Sender as TLabel).Font.Style:=[fsUnderline]; // subrayaría el texto a pasar
  9. end; // del label al pasar por el label

Un saludo


  • 0

#24 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 01 enero 2016 - 04:56

Estas haciendo mucho casting; casting es, "tratar a un objeto como algo que no es".
 
En tu caso estas diciendo, Sender, que es un TObject, conviertete en un TPanel, asi puedo acceder a las propiedades que me interesan
 
El problema es que en ningun lado te aseguras que Sender sea efectivamente un TPanel. Esto lo podes chequear con el operador is 
 

delphi
  1. if Sender is TPanel then
  2. Sender es un TPanel (o descendiente)
  3. else
  4. Sender NO es un TPanel (o descendiente)

Otra cosa es que el codigo queda horrible y se hace largo el aplicar casting en cada instruccion. Mejor esto:
 

delphi
  1. var
  2.   LPanel: TPanel;
  3.   LControl: TControl;
  4.   I: Integer;
  5. begin
  6.   if not(Sender is TPanel) then
  7.     Exit; // salir del metodo, no se ejecuta mas nada
  8.  
  9.   LPanel := Sender as TPanel; // casting pero seguro, ya que arriba me asegure que es un TPanel, de otro modo hubiese salido del metodo y nunca se ejecuta esta linea
  10.   LPanel.Color := clInactiveCaptionText; // ahora puedo acceder a las propiedades de una forma mas elegante y segura
  11.   LPanel.Font.Style := [fsUnderline];
  12.  
  13.   for I := 0 to LPanel.ControlCount - 1 do
  14.   begin
  15.     LControl := LPanel.Controls[I];
  16.     if LControl is TLabel then
  17.     begin
  18.       TLabel(LControl).Color := clInactiveCaptionText;  // otra forma de hacer casting
  19.       TLabel(LControl).Font.Style := [fsUnderline];
  20.     end;
  21.   end;
  22. end;


  • 0

#25 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 01 enero 2016 - 05:01

En realidad si no queres complicarte la vida, y simplemente tenes un TPanel, y dentro de el un TLabel, ya creados en tiempo de diseño, esto funcionaria perfectamente,

 

Siendo lo que te generaria el IDE automaticamente


delphi
  1. interface
  2.  
  3. type
  4. TForm1 = class(TForm)
  5. Panel1: TPanel;
  6. Label1: TLabel;
  7. private
  8. public
  9. end;
  10.  
  11. implementation
  12.  
  13. procedure ...
  14. begin
  15. Panel1.Color := clBlue;
  16. Label1.Color := clWhite;
  17. end;


  • 0

#26 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 02 enero 2016 - 04:29

Que interesante este codigo Agustin Ortu; lo que puedo aprender de el. Pero tengo algunas dudas;

 

porque no has declarado Tlabel en var como Llabel (igual que has hechoc con Lpanel:=Tpanel; y LControl:=TControl)? y así las dos ultimas instrucciones hubiera quedado asi


php
  1. if LControl is LLabel then
  2. begin
  3. LLabel(LControl).Color := clInactiveCaptionText; // otra forma de hacer casting
  4. LLabel(LControl).Font.Style := [fsUnderline];

Según entiendo Tpanel es un contenedor que puede tener más objetos, luego para "recorrer" los objetos dentro del Tpanel  lo hacemos con un FOR

e identificamos el objeto en cuesiton con TControl, eso es lo que saco en conclusiones cierto?

 

Declaras Lpanel:= Tpanel; LControl:=Tcontrol; en el procedimiento en cuestión pero en mi caso como tengo dos metodos Panel1MouseMove y Panel1MouseLeave. En ninguno de ellos he tenido que declarar nada, pero si uso estas variables las tendré que declarar en el Var del Unit para que no me de problemas y la usen los dos métodos, porque como indico en mi codigo en ningun momento se ha inicializado nada  verdad?

 

Que bueno es adquirir buenos hábitos si alguien pueda enseñarlos... gracias Ortu!


  • 0

#27 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 02 enero 2016 - 05:08

Pues analizando veo que el codigo hace unos extraños. Si paso el raton por el Tpanel correcto todo ok (subraya texto del panel y colorea el panel)

Pero si hago que pase por el Tlabel se pone en color blanco el Label y ni subraya.


php
  1. procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  2. Y: Integer);
  3. var
  4. I: Integer;
  5. LPanel:TPanel;
  6. LControl: TControl;
  7. begin
  8. if not (Sender is TPanel) then
  9.  
  10. LPanel:=Sender as TPanel;
  11. LPanel.Color:= clInactiveCaptionText; // actua correctamente
  12. LPanel.Font.Style:= [fsUnderline]; // actua correctamente
  13.  
  14. for I:= 0 to LPanel.ControlCount -1 do
  15. begin
  16. LControl:=Lpanel.Controls[I];
  17. if LControl is TLabel then
  18. begin
  19. TLabel(LControl).Color:= clInactiveCaptionText; // El TLabel se cambia a color blanco.
  20. TLabel(LControl).Font.Style:=[fsUnderline] // idem.
  21. end;
  22. end;

Archivos adjuntos


  • 0

#28 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 02 enero 2016 - 02:54

En la segunda alternativa que presente se trata de aprovechar las variables de instancia del objeto TForm1

 

En Delphi y seguro en Lazarus sea igual, al usar el IDE y agregar un TPanel, automaticamente se genera una variable de instancia en el Form, es decir:


delphi
  1. type
  2. TForm1 = class(TForm)
  3. Panel1: TPanel;
  4. end;

Esto quiere decir que todas las instancias de TForm1, conocen una variable de instancia publica llamada Panel1, de tipo TPanel

 

Esto es perfectamente valido:


delphi
  1. uses
  2. Unit1;
  3.  
  4. procedure TForm2.FormCreate(Sender: TObject);
  5. begin
  6. Form1.Panel1.Caption := 'hola!';
  7. end;

Ahora bien, siendo que todos los form de tipo TForm1 conocen esta variable de instancia Panel, es totalmente valido usarla dentro de los metodos y ahorrarse la parte del Sender

 

Cuando se trata de usar siempre el mismo panel, y siempre el mismo label, y ya estan declarados, es decir, tengo una referencia a los objetos, no hace falta todo el circo de convertir Sender en el TPanel, luego buscar el Label.. usa las variables de instancia que ya estan y fin de la historia :)

 

La parte interesante del Sender entra cuando distintos objetos comparten un mismo evento; incluso hasta podria ser el caso de distintos objetos de distinto tipo.

 

Para no complicarte mas la vida, y darte un ejemplo mas amigable, que pasaria si en vez de tener 1 panel, tenes 2, y los dos tienen que hacer exactamente lo mismo?

 

La solucion mas acertada es, escribir un solo metodo que responda adecuadamente para los 2 paneles. La manera mas directa de resolverlo es usando la tecnica del Sender que comente mas arriba, hacer todo el trabajo por identificar el objeto y luego recorrer dentro de el para buscar el label. 


  • 0

#29 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 02 enero 2016 - 02:59

Con respecto a tu codigo, lo copie tal cual y no puedo reproducir el mismo comportamiento.

 

Solamente puse un TPanel con un TLabel adentro y el mismo codigo en el OnMouseMove; probe usando el Panel tanto con ShowCaption en True como en False y funciona correctamente


  • 0

#30 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 02 enero 2016 - 03:40

:( pues me descoloco un poco. Ya que ese mismo codigo que adjunto está en el OnMouseMove y si el ratón pasa por el panel perfecto (subraya y pone fondo), pero como pase por el TLabel este (quita el subrayada y el fondo) y lo cambia a color blanco el TLabel.

 

En lazarus no aparece la propiedad ShowCaption...

 

Me armaré de valor para seguir probando Agustin Ortu.

 

Un saludo


  • 0

#31 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 03 enero 2016 - 02:05

Nada no hay manera y forma de conseguir el propósito de que se comporte el TLabel como sí lo hace el TPanel...No sé que podré estar haciendo mal


  • 0

#32 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 03 enero 2016 - 02:37

Es muy recomendable seguir el consejo de Agustín sobre el cast empleando el operador As, ya que es la vía más segura. Y ni que decir, que siempre se debe chequear que efectivamente el Sender sea quien dice ser (en este caso Panel).

 

Lo de porqué con el Label te pinta de blanco no te sabría decir... tendría que hacer algunas pruebas. Y en estos días ando medio falto de tiempo. No se si bastaría con probar que valor tiene el Label en su propiedad ParentColor (debería estar en true; y la del Panel en false) y en la propiedad Transparent (debería ser false).

Lo que puedes hacer, y si es que no queda otra opción, es que en ese mismo evento "repintes" al control, forzando al label en cuestión a que tome el mismo color que el del Panel (pero ojo: debe hacerse en orden: 1ro indicar el color del Panel, y luego el del Label) ... aunque viendo el código que exponen tal parece que así hacen... Umm. ¿y si se invoca a un .Refresh del Label?

 

Pero insisto es curioso. Un código como éste tiene que funcionar al 100%:


delphi
  1. procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  2. begin
  3. Panel1.Color := clTeal;
  4. Panel1.Font.Style := Panel1.Font.Style + [fsBold];
  5. Label1.Color := Panel1.Color;
  6. end;
  7.  
  8. procedure TForm1.Panel1MouseLeave(Sender: TObject);
  9. begin
  10. Panel1.Color := clSkyBlue;
  11. Panel1.Font.Style := Panel1.Font.Style - [fsBold];
  12. Label1.Color := Panel1.Color;
  13. end;

Estableciendo ya desde tiempo de diseño las propiedades como he mencionado y obviamente teniendo ya el color en "modo normal" para el Panel, y obviamente dentro de éste dispuesto su Label.

 

Saludos,


  • 0

#33 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 04 enero 2016 - 09:58

Hola Delphius, así no funciona, si lo hace cuando pasas el mouse por encima del Panel, pero sin salir del panel con el ratón, pasas por el Tlabel este ya responde y se cambia a fondo blanco y desaparece el fondo del panel. Lo queo ocurre que el Label no lo interpreta como parte del TPanel, luego al hacer una pasada por el TLabel esté activa el procedimiento Panel1MouseLeave. Sacando una conclusión todo lo que tenga el panel (Label, Image....) al pasar por ese componente no responde a las sentencias. Veo que con el icono que tengo en el propio panel que está dentro del un TImage le ocurre igual que la TLabel.

 

Una pena, pero guardaré el codigo para futuros usos que no sean para estos fines, miraré a ver si puedo hacer algo distinto.

 

Un saludo


  • 0

#34 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 04 enero 2016 - 05:41

Tendría que hacer una prueba completa, y ni que decir, lo más aproximada a lo que tu tienes para recrear tu caso y descubrir cual es el problema.

Pero el código que te puse en mi último post me funciona perfectamente en Windows 8.1. Simplemente puse un Panel y dentro de éste un Label (suelto, sin alineación alguna), configuré las propiedades que cité antes e implementé sólo los métodos que se ven del código.

Al pasar el mouse cambia de color tanto el panel como el label, y lo mismo cuando el mouse abandona el control. Como ves, no hay implementación de eventos para el Label. Y eso que paso el mouse por encima y fuera del label, como también del panel.

Admito que no he probado como se comporta al poner una imagen o si algo de esto también puede incidir.

 

Si sigues con mayores inconvenientes, sigue los consejos: BGRAButton. Puede parecer "intimadante" pero en las pruebas que hice mientras aporté en este hilo no me ha dado ningún problema en absoluto.

 

Saludos,


  • 0

#35 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 04 enero 2016 - 08:29

Buscando un componente para un proyecto que tengo encontré otra alternativa: ECImageMenu, de la suite ECControls.

No le he dado vueltas, apenas lo he visto. Quizá pueda ayudar en algo. Desconozco si tiene algo como resaltado, etc.

 

Saludos,


  • 0

#36 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 04 enero 2016 - 10:05

Tambien puedo confirmar que el codigo de Delphius funciona en Lazarus CodeTyphon bien, usando Windows 10 64 bits y FPC 3.1.1


  • 0

#37 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 05 enero 2016 - 05:11

Desde luego son casos que se me escapan....ya que vuestra ayuda siempre ha sido un fiel reflejo de las soluciones a los problemas que me encuentro, pero con lo testarudo que soy no quiero dejarlo, no ya por obtener el resultado en sí, sino que de este código he aprendido cosas interesantes y al menos quisiera tenerlo funcionando.

 

Como digo, y aparece en la imagen adjunta anterior, al pasar por el hace ese extraño. Configuré las propiedades que Delphius me indicó "...No se si  valor tiene el Label en su propiedad ParentColor (debería estar en true; y la del Panel en false) y en la propiedad Transparent (debería ser false).

 

Como me dijo Agustin_Ortu "...probe usando el Panel tanto con ShowCaption en True como en False y funciona correctamente" no encontré esta propiedad en el componente TPanel.

 

Seguiré trasteando, en aras a no dejarme vencer...Windows XP+SP3 (CT 5.6)

 

Saludos.


  • 0

#38 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 05 enero 2016 - 08:43

Si llego a tener un tiempo disponible por la noche o en los próximos días (aunque no creo que pueda antes del viernes) trataré de replicar tu caso y armo una "demo". En lo que estoy pensando es que quizá pueda ayudar en aplicar un .Refresh al Label inmediatamente después que cambias el color al Label.

Y por cuestiones de rendimiento y para disminuir algunos efectos de parpadeo y de visualización poner la propiedad del form DoubleBuffered en true (lo más habitual es hacerlo en el evento OnCreate del form)

 

Saludos,


  • 0

#39 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 05 enero 2016 - 09:54

Gracias Delphius, yo seguiré dandole vueltas y checkeando opciones que aunque no vayan a ningun lado, pueda dar con el asunto.

 

No desisto porque creo que no debo hacerlo, y porque el aprendizaje se basa en no dejar que el problema de atrape...

 

Si consigo algo nuevo, lo comentaré...

 

Un saludo


  • 0

#40 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 05 enero 2016 - 11:42

Toqueteando la suite BGRA como mi buen amigo Delphius me aconsejó, no se si es problema de C.T que muchos de sus componentes no funcionan bien o es un problema externo. En la pequeña demo que he hecho, el Panel en sus bordes no se visualiza correctamente o al menos eso veo (bpsFrame3d). Y además se aprecia que el icono en su fondo hay zonas black que se ven, y me temo que es consecuencia del icono....

 

Desmotivado por estos lastres visuales y de programación...seguiremos aprendiendo!

 

Un saludo


  • 0




IP.Board spam blocked by CleanTalk.