Динамические часы в Яве - PullRequest
8 голосов
/ 02 июня 2010

Я хочу внедрить часы в моей программе, чтобы отобразить дату и время во время работы программы. Я посмотрел на getCurrentTime() метод и Timer с, но ни один из них, кажется, не делает то, что я хотел бы.

Проблема в том, что я могу узнать текущее время, когда программа загружается, но она никогда не обновляется. Будем весьма благодарны за любые предложения о том, на что обратить внимание!

Ответы [ 7 ]

14 голосов
/ 02 июня 2010

Вам нужно использовать класс 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);
5 голосов
/ 02 июня 2010

Вы должны обновлять текст в отдельной теме каждую секунду.

В идеале вы должны обновлять компонент Swing только в EDT (потоке диспетчера событий), но после того, как я попробовал его на своей машине, использование 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 Я оставляю вам задачу по ее реализации.

3 голосов
/ 15 ноября 2012
   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 );
    } 
2 голосов
/ 02 июня 2010

Для тех, кто предпочитает аналоговый дисплей: Аналоговые часы JApplet .

2 голосов
/ 02 июня 2010

Похоже, у вас может быть концептуальная проблема. Когда вы создаете новый объект java.util.Date, он будет инициализирован до текущего времени. Если вы хотите реализовать часы, вы можете создать компонент с графическим интерфейсом, который постоянно создает новый объект 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
0 голосов
/ 23 февраля 2019
    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();
0 голосов
/ 17 апреля 2015

Обратите внимание, что здесь используется метод 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);
...