2010-06-02 31 views
8

Quiero implementar un reloj dentro de mi programa para diusplay la fecha y la hora mientras se ejecuta el programa. He investigado el método getCurrentTime() y Timer s, pero ninguno de ellos parece hacer lo que me gustaría.Reloj dinámico en java

El problema es que puedo obtener la hora actual cuando se carga el programa, pero nunca se actualiza. ¡Cualquier sugerencia sobre algo para mirar sería muy apreciada!

+1

no hago swing ampliamente, por lo que hay una respuesta detallada de la mía, pero Google parece dar suficientes pistas: http: // www .google.com/search? q = java + swing + clock Hasta el punto: necesita actualizar el reloj * usted mismo * cada vez en un hilo de fondo. – BalusC

+1

@BalusC pero lo hace google extensamente;) – Bozho

Respuesta

13

Lo que necesita hacer es utilizar la clase Timer de Swing.

Simplemente haga que se ejecute cada segundo y actualice el reloj con la hora actual.

Timer t = new Timer(1000, updateClockAction); 
t.start(); 

Esto hará que el updateClockAction se dispare una vez por segundo. Se ejecutará en el EDT.

Puede hacer que el updateClockAction similar al siguiente:

ActionListener updateClockAction = new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     // Assumes clock is a custom component 
     yourClock.setTime(System.currentTimeMillis()); 
     // OR 
     // Assumes clock is a JLabel 
     yourClock.setText(new Date().toString()); 
    } 
} 

Debido a esto actualiza el reloj cada segundo, el reloj se apagará por 999ms en el peor de los casos. Para aumentar esta cifra a un margen de error de 99 ms peor de los casos, puede aumentar la frecuencia de actualización:

Timer t = new Timer(100, updateClockAction); 
+1

Hice una prueba y la actualización fue siempre de medio segundo detrás de usar javax.swing.Timer pero, no sé por qué – OscarRyz

2

Esto suena como que podría tener un problema conceptual. Cuando crea un nuevo objeto java.util.Date, se inicializará a la hora actual. Si desea implementar un reloj, puede crear un componente GUI que crea constantemente un nuevo objeto Date y actualiza la pantalla con el último valor.

¿Alguna pregunta que puede tener es cómo hacer algo de manera repetida en un horario? Puede tener un bucle infinito que crea un nuevo objeto Fecha y luego llama a Thread.sleep (1000) para que obtenga la última hora cada segundo. Una forma más elegante de hacer esto es usar un TimerTask. Normalmente, haces algo como:

private class MyTimedTask extends TimerTask { 

    @Override 
    public void run() { 
     Date currentDate = new Date(); 
     // Do something with currentDate such as write to a label 
    } 
} 

Luego, a invocarla, lo que haría algo como:

Timer myTimer = new Timer(); 
myTimer.schedule(new MyTimedTask(), 0, 1000); // Start immediately, repeat every 1000ms 
+4

Este código probablemente funciona bien, pero ya que está utilizando Java.util.Timer, debe asegurarse de usar 'SwingUtilities.invokeLater()' para actualizar la GUI. – jjnguy

+0

Definitivamente. Fui deliberadamente vago sobre el tema "Hacer algo", no quería introducir demasiadas cosas al mismo tiempo. – PhilDin

5

Usted tiene que actualizar el texto en un hilo separado cada segundo.

Idealmente debería actualizar los componentes de impulsión solo en el EDT (evento hilo despachador), pero, después de lo probé en mi máquina, usando Timer.scheduleAtFixRate me dio mejores resultados:

java.util.Timer http://img175.imageshack.us/img175/8876/capturadepantalla201006o.png

El javax.swing. versión temporizador fue siempre alrededor de la mitad segundo por detrás:

javax.swing.Timer http://img241.imageshack.us/img241/2599/capturadepantalla201006.png

realmente no sé por qué.

Aquí está el código fuente completo:

package clock; 

import javax.swing.*; 
import java.util.*; 
import java.text.SimpleDateFormat; 

class Clock { 
    private final JLabel time = new JLabel(); 
    private final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm"); 
    private int currentSecond; 
    private Calendar calendar; 

    public static void main(String [] args) { 
     JFrame frame = new JFrame(); 
     Clock clock = new Clock(); 
     frame.add(clock.time); 
     frame.pack(); 
     frame.setVisible(true); 
     clock.start(); 
    } 
    private void reset(){ 
     calendar = Calendar.getInstance(); 
     currentSecond = calendar.get(Calendar.SECOND); 
    } 
    public void start(){ 
     reset(); 
     Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask(){ 
      public void run(){ 
       if(currentSecond == 60) { 
        reset(); 
       } 
       time.setText(String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond)); 
       currentSecond++; 
      } 
     }, 0, 1000); 
    } 
} 

Aquí está la fuente modificado usando javax.swing.Temporizador

public void start(){ 
     reset(); 
     Timer timer = new Timer(1000, new ActionListener(){ 
     public void actionPerformed(ActionEvent e) { 
       if(currentSecond == 60) { 
        reset(); 
       } 
       time.setText(String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond)); 
       currentSecond++; 
      } 
     }); 
     timer.start(); 
    } 

Probablemente debería cambiar la forma en que se calcula la cadena con la fecha, pero no creo que ese es el problema aquí

He leído, que, desde Java 5 del recomendado es: ScheduledExecutorService Te dejo la tarea de implementarlo.

+0

Interesante, me pregunto por qué está todo .5 segundos atrás. – jjnguy

+0

No sé, probablemente era el tiempo de inicio (para entrar en el EDT o algo así) pero no pude recuperarlos. – OscarRyz

3
public void start(){ 
     reset(); 
     ScheduledExecutorService worker = Executors.newScheduledThreadPool(3); 
     worker.scheduleAtFixedRate(new Runnable(){ 
      public void run(){ 
       if(currentSecond == 60) { 
        reset(); 
       } 
       time.setText(String.format("%s:%02d", sdf.format(calendar.getTime()), currentSecond)); 
       currentSecond++; 
      } 
     }, 0, 1000 ,TimeUnit.MILLISECONDS); 
    } 
0

Nota scheduleAtFixedRate el método se utiliza aquí

 // Current time label 
     final JLabel currentTimeLabel = new JLabel(); 
     currentTimeLabel.setFont(new Font("Monospace", Font.PLAIN, 18)); 
     currentTimeLabel.setHorizontalAlignment(JTextField.LEFT); 

     // Schedule a task for repainting the time 
     final Timer currentTimeTimer = new Timer(); 
     TimerTask task = new TimerTask() { 
      @Override 
      public void run() { 
       currentTimeLabel.setText(TIME_FORMATTER.print(System.currentTimeMillis())); 
      } 
     }; 

     currentTimeTimer.scheduleAtFixedRate(task, 0, 1000);