Dynamic Clock in java

后端 未结 7 1055
我在风中等你
我在风中等你 2020-12-16 02:22

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

相关标签:
7条回答
  • 2020-12-16 03:02

    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);
    
    0 讨论(0)
  • 2020-12-16 03:02

    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.

    0 讨论(0)
  • 2020-12-16 03:12

    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
    
    0 讨论(0)
  • 2020-12-16 03:16
       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 讨论(0)
  • 2020-12-16 03:19

    For those preferring an analog display: Analog Clock JApplet.

    0 讨论(0)
  • 2020-12-16 03:22

    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);
    
    0 讨论(0)
提交回复
热议问题