Я хочу внедрить часы в моей программе, чтобы отобразить дату и время во время работы программы. Я изучил метод getCurrentTime()
и Timer
, но ни один из них, кажется, не делает то, что я хотел бы.
Проблема в том, что я могу узнать текущее время, когда программа загружается, но она никогда не обновляется. Будем весьма благодарны за любые предложения по поводу того, на что обратить внимание!
Что вам нужно сделать, так это использовать класс 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);
Для тех, кто предпочитает аналоговый дисплей: Аналоговые часы JApplet .
Вы должны обновлять текст в отдельном потоке каждую секунду.
В идеале вы должны обновлять компонент Swing только в EDT (поток диспетчера событий), но после того, как я попробовал его на своей машине, использование Timer.scheduleAtFixRate дало мне лучшие результаты:
java.util. Таймер 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 Я оставляю вам задачу реализовать его.
Похоже, что у вас концептуальная проблема. Когда вы создаете новый объект 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