9

我想在我的程序中实现一个时钟,以便在程序运行时显示日期和时间。我已经研究了getCurrentTime()方法和Timers,但他们似乎都没有做我想做的事。

问题是我可以获得程序加载但它永远不会更新的当前时间。任何关于要研究的东西的建议将不胜感激!

4

7 回答 7

15

你需要做的是使用 Swing 的Timer类。

让它每秒运行一次,并用当前时间更新时钟。

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

这将导致updateClockAction每秒触发一次。它将在 EDT 上运行。

您可以进行updateClockAction类似以下操作:

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

因为这会每秒更新时钟,所以在更糟糕的情况下,时钟将关闭 999 毫秒。要将其增加到 99 毫秒的更坏情况误差范围,您可以增加更新频率:

Timer t = new Timer(100, updateClockAction);
于 2010-06-02T16:53:14.940 回答
5

您必须每秒在单独的线程中更新文本。

理想情况下,您应该只在 EDT(事件调度程序线程)中更新 swing 组件,但是,在我的机器上尝试过之后,使用Timer.scheduleAtFixRate给了我更好的结果:

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

javax.swing.Timer 版本总是落后大约半秒:

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

我真的不知道为什么。

这是完整的来源:

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

这是使用 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();
    }

可能我应该改变计算日期字符串的方式,但我认为这不是问题所在

我已经读过,从 Java 5 开始,推荐的是:ScheduledExecutorService我留给你实现它的任务。

于 2010-06-02T17:53:47.160 回答
3

这听起来像你可能有一个概念问题。当您创建一个新的 java.util.Date 对象时,它将被初始化为当前时间。如果你想实现一个时钟,你可以创建一个 GUI 组件,它不断地创建一个新的 Date 对象并用最新的值更新显示。

您可能有一个问题是如何按计划重复做某事?您可以有一个无限循环,创建一个新的 Date 对象,然后调用 Thread.sleep(1000) 以便它每秒获取最新时间。一种更优雅的方法是使用 TimerTask。通常,您会执行以下操作:

private class MyTimedTask extends TimerTask {

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

然后,要调用它,您可以执行以下操作:

Timer myTimer = new Timer();
myTimer.schedule(new MyTimedTask (), 0, 1000);  // Start immediately, repeat every 1000ms
于 2010-06-02T17:10:58.830 回答
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 );
    } 
于 2012-11-15T12:26:18.910 回答
2

对于那些喜欢模拟显示器的人:Analog Clock JApplet

于 2010-06-02T18:27:07.393 回答
0

注意scheduleAtFixedRate这里使用的方法

        // 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);
于 2015-04-17T18:08:39.017 回答
0
    Timer timer = new Timer(1000, (ActionEvent e) -> {
        DateTimeFormatter myTime = DateTimeFormatter.ofPattern("HH:mm:ss");
        LocalDateTime now = LocalDateTime.now(); 
        jLabel1.setText(String.valueOf(myTime.format(now)));
    });
    timer.setRepeats(true);
    timer.start();
于 2019-02-23T02:04:45.940 回答