Ir al contenido


Foto

Mostrar un mensaje en pantalla 3 seg. y luego cerrarlo

timer starttimer stoptimer

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

#1 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 16 diciembre 2015 - 12:46

Hola a todos.

 

Quiero hacer algo muy sencillo pero que se me está resistiendo bastante. Utilizo codetyphon v 5.50.

 

Quiero mostrar un mensaje en un panel por ejemplo, pero sólo durante un periodo muy corto de tiempo, pongamos 3 segundos, y al cabo de ese tiempo, que se cierre solo el mensaje.

El mensaje lo podemos mostrar/ocultar con la propiedad visible del panel poniéndola en true o false.

 

Ahora bien ¿cómo se hace? ¿Hay algún componente de CT que haga eso? He visto que hay media docena de timers, pero la documentación es parca y no encuentro algo que ejecute un evento durante un periodo de tiempo.

 

El caso es que trasteando con un timer normal y corriente he conseguido hacerlo, pero no entiendo del todo cómo lo he hecho. Os pongo el código.

 

En un formulario pongo un botón, un timer (con la propiedad enabled a false) y un panel que es el que mostrará el mensaje y que por defecto tiene visible en false (mensaje oculto).

El timer le pongo el interval en 3000 ms (3 s), el tiempo que se muestra el mensaje.


php
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3. timer1.Enabled := True; //al darle al botón pongo en marcha el timer
  4.  
  5. procedure TForm1.Timer1StartTimer(Sender: TObject);
  6. begin
  7. Panel1.Visible := True; //hago visible el panel que contiene el mensaje
  8. Panel1.Repaint; //lo repinto
  9.  
  10. procedure TForm1.Timer1StopTimer(Sender: TObject);
  11. begin
  12. Panel1.Visible := False; //hago invisible el panel (oculto el mensaje)
  13.  
  14. procedure TForm1.Timer1Timer(Sender: TObject);
  15. begin
  16. Panel1.Visible := True; //codigo repetido en starttimer
  17. Panel1.Repaint; //codigo repetido en starttimer
  18. timer1.Enabled := False; //lo desactivo para que solo lo ponga el marcha la pulsación del botón

Como os digo, con este código funciona bien pero no lo comprendo del todo. Como indico en los comentarios del código, hay código duplicado en el evento timer y en el evento starttimer. Si quito el código duplicado en cualquiera de los dos eventos, NO funciona. Si lo quito de startimer, el mensaje no se muestra y si lo quito del evento timer, el mensaje se muestra pero no se oculta nunca.

 

En fín, que antes de utilizar un código que funciona pero del que dudo si es una chapuza, me he pasado por aquí y os pregunto. ¿Ideas? ¿Es correcto el código?

 

Un saludo.


  • 0

#2 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 16 diciembre 2015 - 02:28

No hace falta que uses el evento OnStopTimer

 

OnStopTimer se dispara "solamente" cuando se invoca al metodo protegido KillTimer.

 

KillTimer se invoca:

 

1. En el destructor

2. En el metodo UpdateTimer

 

UpdateTimer, es invocado desde muchas partes; por ejemplo, al cambiar el valor de la propiedad Enabled

 

Asi que, basicamente, todo lo que invoque a UpdateTimer te va a terminar invocando a OnStopTimer

 

En Delphi simplemente se tiene el evento OnTimer

 

 

El codigo es mas sencillo:

 

 

Simplemente, en OnStartTimer pones Visible a True, y en OnTimer pones Visible a False

 

El repaint creo que no es necesario

 

El evento OnTimer se dispara cuando pasa el tiempo indicado en la propiedad Interval


  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 16 diciembre 2015 - 02:29

No utilizo Lazarus pero si fuese el mismo funcionamiento que en Delphi yo haría lo siguiente:


delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3. timer1.Enabled := True;
  4. Panel1.Visible := True;
  5. end;
  6.  
  7. procedure TForm1.Timer1Timer(Sender: TObject);
  8. begin
  9. Panel1.Visible := False;
  10. timer1.Enabled := False;
  11. end;

Saludos


Editado por egostar, 16 diciembre 2015 - 05:30 .
Nuestro amigo Agustín Ortu, ya lo ha explicado muy bien.

  • 0

#4 AngelF

AngelF

    Advanced Member

  • Miembros
  • PipPipPip
  • 100 mensajes
  • LocationValencia - España

Escrito 16 diciembre 2015 - 03:16

Ok, muchas gracias, Agustín y Egostar. Vuestros códigos funcionan perfectamente.

 

Ya entiendo un poco mejor el funcionamiento del timer.

Recapitulando:

 

Evento StartTimer: --> Se pone en marcha cuando se hace timer1.enabled=true;

Evento Timer --> Se pone en marcha una vez han transcurrido los milisegundos especificados en la propiedad interval y se repite cíclicamente mientras la propiedad enabled esté en true.

Evento StopTimer --> No necesario.


  • 1

#5 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 16 diciembre 2015 - 03:59

Ojo, no digo que no sea necesario. Pero los amigos de Lazarus le pusieron un nombre que presta a confusion

 

Mejor seria

 

OnTimer

OnTimerEnabled

OnTimerDisabled


  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 16 diciembre 2015 - 05:01

Ojo, no digo que no sea necesario. Pero los amigos de Lazarus le pusieron un nombre que presta a confusion

 

Mejor seria

 

OnTimer

OnTimerEnabled

OnTimerDisabled

 

En realidad el nombre de los eventos está bien. Tu propuesta demuestra justamente que cuando se presenta una dualidad del tipo booleana esto se controla por una propiedad de dicho tipo, o bien por un método (como podría ser InitTimer por ejemplo para el caso de establecer en true dicha propiedad). Los nombres de los eventos deben reflejar procesos desde un contexto "superior" o que se necesita notificar de algo que otro objeto (y por tanto de otro contexto) está interesado.  Lo errado es sugerir algo que es derivado (o que incluso puede saberse por una) por el nombre de una propiedad. OnStartTimer es un nombre significativo para un evento hacia afuera, en cambio OnTimerEnabled sugiere más un tipo de evento que se espera trabajar de manera interna.

 

Saludos,


  • 0

#7 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 16 diciembre 2015 - 05:50

Es cierto lo que decis

 

Por otro lado, el tema de ponerle nombre a las cosas, yo estoy de acuerdo y ya se ha dicho por ahi, es uno de los retos mas grandes para los programadores

 

Yo muchas veces me encuentro con una idea en la cabeza, incluso hasta con cierto codigo, abro Delphi, creo una unidad, y.. que nombre le pongo? :)

 

A mi sencillamente me causo confusion la implementacion del TTimer de Lazarus (y no, no estoy acostumbrado al de Delphi, nunca lo he usado mas que para jugar)

 

En cualquier caso, si los eventos estan bien, lo que se podria cambiar es la propiedad Enabled.

 

Podrian ponerse dos metodos:

 

Timer.Start

Timer.Stop

 

Y una propiedad de solo lectura IsRunning o similar

 

De esa forma, me resulta mas amigable e intuitivo:  "Bien, invoco a Timer.Start, seguro que ahora se ejecuta el evento OnTimerStarted". Lo mismo para el OnTimerStopped.

 

Saludos


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 diciembre 2015 - 04:16

¿Habéis pensado en la posibilidad de usar la API MessageBoxTimeOut? Un ejemplo

 

 

Saludos.


  • 2

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 17 diciembre 2015 - 12:04

Lo que comenta escafandra me hizo acordar del componente TPopupNotifier. Este componente sirve para mostrar notificaciones como al estilo de Facebook, y al menos en diseño, ofrece la posibilidad de que se indique cuanto tiempo debe estar visible para luego ocultarse:


delphi
  1. popupnotifier1.vNotifierForm.HideInterval:= 2000;
  2. popupnotifier1.vNotifierForm.AutoHide := true;
  3. popupnotifier1.Show;

Pero por algún motivo no funciona el auto ocultamiento. Estuve explorando un poco el código y es poco enreversado, he visto que entre la rama de herencia una de las clases dispone del TCustomTimer, pero no encuentro que ante algún Show o Visible = true se de inicio a dicho timer.

 

La otra posibilidad es TTrayIcon, que funciona perfectamente para notificaciones en la barra de sistema y se oculta solito tras un tiempo.

 

Saludos,


  • 1

#10 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 diciembre 2015 - 06:02

Lo que comenta escafandra me hizo acordar del componente TPopupNotifier.

Quizás esto sirva: Ventana desplegable translúcida, una alternativa a AnimateWindow
 

La otra posibilidad es TTrayIcon, que funciona perfectamente para notificaciones en la barra de sistema y se oculta solito tras un tiempo.

Me hiciste recordar este truco: Escribir una notificación en el SysTray


Saludos.


  • 1

#11 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 diciembre 2015 - 08:46

Hace poco estaba buscando la forma de cerrar un form en 3 segundos, para tu caso te puede servir esto:

 

1. Debes tener tanto el Panel y el timer  a FALSE, luego pruebas este código:


php
  1. var
  2.   Form1: TForm1;
  3.   sec: integer;   // nos servirá para controlar los 3 segundos
  4.  
  5. procedure TForm1.Button1Click(Sender: TObject); // al dar clic al botón sucederá lo siguiente
  6. begin
  7.   sec:=0;   // reseteamos siempre a 0 sino el conteó nunca acabaría
  8.   Panel1.Visible:=true;     // volvemos visible el Panel
  9.   Timer1.Enabled:=true;  // Arrancamos el Timer
  10. end; 
  11.  
  12. procedure TForm1.Timer1Timer(Sender: TObject);   // sucesos que ocurriran en el Timer
  13. begin
  14.   sec:=sec+1;    // siendo primeramente el valor de "sec" = 0  le sumamos +1
  15.   if sec=3 then   // Si en caso el valor de "sec" es = 3, entonces son tres segundos, por lo tanto hacemos lo siguiente...
  16.   begin
  17.   Panel1.Visible:=false;     // Ocultamos el Panel
  18.   Timer1.Enabled:=false;  // Desactivamos el Timer para que pare el conteo
  19.   end;

Espero te sirva amigo de un Novato a otro :) :) :)


  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 diciembre 2015 - 11:40

Hace poco estaba buscando la forma de cerrar un form en 3 segundos, para tu caso te puede servir esto:

 

1. Debes tener tanto el Panel y el timer  a FALSE, luego pruebas este código:


php
  1. var
  2.   Form1: TForm1;
  3.   sec: integer;   // nos servirá para controlar los 3 segundos
  4.  
  5. procedure TForm1.Button1Click(Sender: TObject); // al dar clic al botón sucederá lo siguiente
  6. begin
  7.   sec:=0;   // reseteamos siempre a 0 sino el conteó nunca acabaría
  8.   Panel1.Visible:=true;     // volvemos visible el Panel
  9.   Timer1.Enabled:=true;  // Arrancamos el Timer
  10. end; 
  11.  
  12. procedure TForm1.Timer1Timer(Sender: TObject);   // sucesos que ocurriran en el Timer
  13. begin
  14.   sec:=sec+1;    // siendo primeramente el valor de "sec" = 0  le sumamos +1
  15.   if sec=3 then   // Si en caso el valor de "sec" es = 3, entonces son tres segundos, por lo tanto hacemos lo siguiente...
  16.   begin
  17.   Panel1.Visible:=false;     // Ocultamos el Panel
  18.   Timer1.Enabled:=false;  // Desactivamos el Timer para que pare el conteo
  19.   end;

Espero te sirva amigo de un Novato a otro :) :) :)

 

Eso va a funcionar mientras en la propiedad Interval del TTimer esté el valor 1000. La propiedad Interval cuenta en milisegundos.

 

Aunque se puede prescindir de contar los segundos. Directamente se puede establecer el timer en 3000 (3 seg) y ni bien se ejecuta (mediante Enabled := true) ahí mismo en el evento OnTimer inmediatamente poner en false la propiedad Enabled.

 

Saludos,


  • 0




IP.Board spam blocked by CleanTalk.