【问题标题】:Dynamic Clock in javajava中的动态时钟
【发布时间】:2010-06-02 16:41:09
【问题描述】:

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

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

【问题讨论】:

  • 我没有广泛使用 Swing,所以我没有详细回答,但谷歌似乎给出了足够的提示:google.com/search?q=java+swing+clock 重点:你需要更新时钟你自己 i> 每次都在后台线程中。
  • @BalusC 但你广泛使用谷歌 ;)

标签: java swing clock


【解决方案1】:

你需要做的是使用 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);

【讨论】:

  • 我做了一个测试,使用 javax.swing.Timer 更新总是落后大约半秒,但我不知道为什么
【解决方案2】:

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

理想情况下,您应该只在 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 我留给你实现它的任务。

【讨论】:

  • 我不知道,可能是启动时间(进入 EDT 什么的),但我无法恢复它们。
【解决方案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

【讨论】:

  • 这段代码可能运行良好,但由于您使用的是 Java.util.Timer,因此您需要确保使用 SwingUtilities.invokeLater() 来更新 GUI。
  • 当然。我故意对“做某事”这一点含糊其辞,我不想同时介绍太多东西。
【解决方案4】:
   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 );
    } 

【讨论】:

    【解决方案5】:

    对于喜欢模拟显示器的用户:Analog Clock JApplet

    【讨论】:

      【解决方案6】:

      注意这里使用的是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);
      

      【讨论】:

        【解决方案7】:
            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();
        

        【讨论】:

        • 嗨,欢迎来到 Stack Overflow。在回答已经有很多答案的问题时,请务必添加一些额外的见解,说明为什么您提供的回复是实质性的,而不是简单地呼应原始发帖人已经审查过的内容。这在您提供的“纯代码”答案中尤其重要。
        猜你喜欢
        • 2020-01-02
        • 2020-06-19
        • 1970-01-01
        • 1970-01-01
        • 2011-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多