Dynamic Clock in java

2019-01-24 10:47发布

问题:

I want to implement a clock within my program to diusplay the date and time while the program is running. I have looked into the getCurrentTime() method and Timers but none of them seem to do what I would like.

The problem is I can get the current time when the program loads but it never updates. Any suggestions on something to look into would be greatly appreciated!

回答1:

What you need to do is use Swing's Timer class.

Just have it run every second and update the clock with the current time.

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

This will cause the updateClockAction to fire once a second. It will run on the EDT.

You can make the updateClockAction similar to the following:

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()); 
    }
}

Because this updates the clock every second, the clock will be off by 999ms in a worse case scenario. To increase this to a worse case error margin of 99ms, you can increase the update frequency:

Timer t = new Timer(100, updateClockAction);


回答2:

You have to update the text in a separate thread every second.

Ideally you should update swing component only in the EDT ( event dispatcher thread ) but, after I tried it on my machine, using Timer.scheduleAtFixRate gave me better results:

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

The javax.swing.Timer version was always about half second behind:

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

I really don't know why.

Here's the full source:

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 );
    }
}

Here's the modified source using javax.swing.Timer

    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();
    }

Probably I should change the way the string with the date is calculated, but I don't think that's the problem here

I have read, that, since Java 5 the recommended is: ScheduledExecutorService I leave you the task to implement it.



回答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 );
    } 


回答4:

This sounds like you might have a conceptual problem. When you create a new java.util.Date object, it will be initialised to the current time. If you want to implement a clock, you could create a GUI component which constantly creates a new Date object and updates the display with the latest value.

One question you might have is how to repeatedly do something on a schedule? You could have an infinite loop that creates a new Date object then calls Thread.sleep(1000) so that it gets the latest time every second. A more elegant way to do this is to use a TimerTask. Typically, you do something like:

private class MyTimedTask extends TimerTask {

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

Then, to invoke it, you would do something like:

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


回答5:

For those preferring an analog display: Analog Clock JApplet.



回答6:

Note the method scheduleAtFixedRate is used here

        // 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);


回答7:

This is the dynamic clock using simple java code not swing ....

 import java.awt.AWTException;
 import java.awt.Robot;
 import java.awt.event.KeyEvent;
 import java.util.Calendar;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.Delayed;

 public class timer
 {

 public static void main(String[] args)
 {

 Timer timer = new Timer();

     timer.scheduleAtFixedRate(new TimerTask()
     {
        public void run()
        {
            Robot robbie;

            int second, minute, hour;
            Calendar date = Calendar.getInstance();
            second = date.get(Calendar.SECOND);
            minute = date.get(Calendar.MINUTE);
            hour = date.get(Calendar.HOUR);
            System.out.println("Current time is  " + hour + " : " + 
            minute +" : " + second);

            try
            {
                robbie = new Robot();
                robbie.keyPress(KeyEvent.VK_ALT);
                robbie.keyPress(KeyEvent.VK_SHIFT);
                robbie.keyPress(KeyEvent.VK_Q);
                robbie.keyRelease(KeyEvent.VK_ALT);
                robbie.keyRelease(KeyEvent.VK_SHIFT);
                robbie.keyRelease(KeyEvent.VK_Q);
                robbie.keyPress(KeyEvent.VK_C);
                robbie.keyRelease(KeyEvent.VK_C);
                robbie.keyPress(KeyEvent.VK_SHIFT);
                robbie.keyPress(KeyEvent.VK_F10);
                robbie.keyPress(KeyEvent.VK_R);
                robbie.keyRelease(KeyEvent.VK_SHIFT);
                robbie.keyRelease(KeyEvent.VK_F10);
                robbie.keyRelease(KeyEvent.VK_R);
            } catch (AWTException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
             }
          }
       }, 1 * 500, 1 * 500);
    }
 }


标签: java swing clock