我想在我的程序中实现一个时钟,以便在程序运行时显示日期和时间。我已经研究了getCurrentTime()
方法和Timer
s,但它们似乎都没有按照我的意愿行事。
问题是我可以在程序加载时得到当前时间,但它永远不会更新。任何有待观察的建议都将不胜感激!
答案 0 :(得分:14)
您需要做的是使用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());
}
}
因为这会每秒更新一次时钟,所以在更糟糕的情况下,时钟会关闭999ms。要将此值增加到更差的99ms的错误边际,您可以增加更新频率:
Timer t = new Timer(100, updateClockAction);
答案 1 :(得分: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我告诉你实现它的任务。
答案 2 :(得分: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 );
}
答案 3 :(得分:2)
这听起来像你可能有一个概念上的问题。创建新的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
答案 4 :(得分:2)
对于那些喜欢模拟显示器的人:Analog Clock JApplet。
答案 5 :(得分: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);
答案 6 :(得分: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();