2010-06-02 44 views
8

Tôi muốn triển khai đồng hồ trong chương trình của mình để diusplay ngày và giờ trong khi chương trình đang chạy. Tôi đã xem xét các phương pháp getCurrentTime()Timer s nhưng không ai trong số họ dường như làm những gì tôi muốn.Đồng hồ động trong java

Vấn đề là tôi có thể nhận được thời gian hiện tại khi chương trình tải nhưng không bao giờ cập nhật. Bất kỳ đề xuất về một cái gì đó để xem xét sẽ được đánh giá rất nhiều!

+1

tôi không làm Swing rộng rãi, vì vậy có câu trả lời chi tiết từ mỏ, nhưng Google dường như cung cấp đủ gợi ý: http: // www .google.com/search? q = java + swing + clock Tới điểm: bạn cần cập nhật đồng hồ * chính mình * mọi lúc trong chuỗi nền. – BalusC

+1

@BalusC nhưng bạn làm google rộng rãi;) – Bozho

Trả lời

13

Điều bạn cần làm là sử dụng lớp Timer của Swing.

Chỉ chạy nó sau mỗi giây và cập nhật đồng hồ với thời gian hiện tại.

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

Điều này sẽ gây ra updateClockAction để kích hoạt mỗi giây một lần. Nó sẽ chạy trên EDT.

Bạn có thể làm cho updateClockAction tương tự như sau:

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

Bởi vì đây cập nhật đồng hồ mỗi giây, đồng hồ sẽ được tắt bởi 999ms trong một trường hợp kịch bản tồi tệ hơn. Để tăng tỷ lệ này lên tỷ lệ lỗi của trường hợp xấu hơn là 99ms, bạn có thể tăng tần suất cập nhật:

Timer t = new Timer(100, updateClockAction); 
+1

Tôi đã làm một thử nghiệm và cập nhật luôn luôn khoảng nửa giây sau khi sử dụng javax.swing.Timer nhưng, tôi không biết tại sao – OscarRyz

2

Điều này nghe có vẻ như bạn có vấn đề về khái niệm. Khi bạn tạo một đối tượng java.util.Date mới, nó sẽ được khởi tạo vào thời điểm hiện tại. Nếu bạn muốn triển khai đồng hồ, bạn có thể tạo một thành phần GUI liên tục tạo đối tượng Date mới và cập nhật hiển thị với giá trị mới nhất.

Một câu hỏi mà bạn có thể có là làm thế nào để liên tục làm điều gì đó theo lịch biểu? Bạn có thể có một vòng lặp vô hạn tạo ra một đối tượng Date mới sau đó gọi Thread.sleep (1000) để nó nhận được thời gian mới nhất mỗi giây. Một cách thanh lịch hơn để thực hiện việc này là sử dụng TimerTask. Thông thường, bạn làm như sau:

private class MyTimedTask extends TimerTask { 

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

Sau đó, để gọi nó, bạn sẽ làm điều gì đó như:

Timer myTimer = new Timer(); 
myTimer.schedule(new MyTimedTask(), 0, 1000); // Start immediately, repeat every 1000ms 
+4

Mã này có thể hoạt động tốt, nhưng vì bạn đang sử dụng Java.util.Timer, bạn cần đảm bảo rằng bạn sử dụng 'SwingUtilities.invokeLater()' để cập nhật GUI. – jjnguy

+0

Chắc chắn. Tôi đã cố tình mơ hồ về bit "Do Something", tôi không muốn giới thiệu quá nhiều thứ cùng một lúc. – PhilDin

5

Bạn cần phải cập nhật các văn bản trong một thread riêng biệt mỗi giây.

Lý tưởng nhất là bạn nên cập nhật phần đu duy nhất trong EDT (sự kiện điều phối thread) nhưng, sau khi tôi đã thử nó trên máy tính của tôi, sử dụng Timer.scheduleAtFixRate đã cho tôi kết quả tốt hơn:

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

Các javax.swing. Phiên bản hẹn giờ luôn cách khoảng nửa giây sau:

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

Tôi thực sự không biết tại sao.

Đây là nguồn đầy đủ:

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

Đây là nguồn biến đổi sử dụng 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(); 
    } 

Có lẽ tôi nên thay đổi cách chuỗi với ngày được tính, nhưng tôi không nghĩ đó là vấn đề ở đây

Tôi đã đọc, rằng, kể từ Java 5 đề nghị là: ScheduledExecutorService Tôi để lại cho bạn nhiệm vụ để thực hiện nó.

+0

Thú vị, tôi tự hỏi tại sao nó là toàn bộ .5 giây sau. – jjnguy

+0

Tôi không biết, có lẽ đó là thời gian khởi động (để tham gia vào EDT hoặc một cái gì đó) nhưng tôi không thể phục hồi chúng. – OscarRyz

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

Lưu ý phương pháp scheduleAtFixedRate được sử dụng ở đây

 // 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); 
Các vấn đề liên quan