最近在完成學校課程的java平時作業,要實現一個計時器,包含開始、暫停以及重置三個功能。由於老師規定要用這個timer類,也就去學習了一下,順便記錄一下。
首先呢去查了一下java手冊上的東西,發現timer的構造函數是這么解釋的(拿翻譯機翻譯了)
public class Timer extends Object implements Serializable
在指定時間間隔觸發一個或多個 ActionEvent
。一個示例用法是動畫對象,它將 Timer
用作繪制其幀的觸發器。
設置計時器的過程包括創建一個 Timer
對象,在該對象上注冊一個或多個動作偵聽器,以及使用 start
方法啟動該計時器。例如,以下代碼創建並啟動一個每秒(該時間由 Timer
構造方法的第一個參數指定)觸發一次動作事件的計時器。Timer
構造方法的第二個參數指定接收計時器動作事件的偵聽器。
int delay = 1000; //milliseconds ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { //...Perform a task... } }; new Timer(delay, taskPerformer).start();
構造 Timer
時要指定一個延遲參數和一個 ActionListener
。延遲參數用於設置初始延遲和事件觸發之間的延遲(以毫秒為單位)。啟動了計時器后,它將在向已注冊偵聽器觸發第一個 ActionEvent
之前等待初始延遲。第一個事件之后,每次超過事件間延遲時它都繼續觸發事件,直到被停止。
構造之后,可以單獨更改初始延遲和事件間延遲,並且可以添加其他 ActionListener
。
如果希望計時器只在第一次時觸發然后停止,可以對計時器調用 setRepeats(false)
。
盡管所有 Timer
都使用一個共享線程(由第一個執行操作的 Timer
對象創建)執行等待,但是 Timer
的動作事件處理程序還會在其他線程(事件指派線程上)執行。這意味着 Timer
的操作處理程序可以安全地在 Swing 組件上執行操作。但是,它也意味着處理程序必須快速執行以保證 GUI 作出響應。
在 1.3 版本中,向 Java 平台添加了另一個 Timer
類:java.util.Timer
。該類和 javax.swing.Timer
的基本功能相同,但是 java.util.Timer
更常用,功能更多。javax.swing.Timer
有兩個特征,它們可以讓使用 GUI 更方便。首先,其事件處理程序都是 GUI 程序員所熟悉的,並且可以更簡單地處理事件指派線程。第二,其自動線程共享意味着不必采取特殊步驟來避免生成過多線程。相反,計時器使用同一個線程讓光標閃爍、使工具提示顯示等等。
通過查看 The Java Tutorial 中的 How to Use Timers 一節,可以找到使用計時器的更詳細的文檔和幾個示例。有關在此 Timer
類和 java.util.Timer
之間進行選擇的更多示例和幫助信息,請參閱 The Swing Connection 中的 Using Timers in Swing Applications 一文。
警告:此類的序列化對象與以后的 Swing 版本不兼容。當前序列化支持適用於短期存儲,或適用於在運行相同 Swing 版本的應用程序之間進行 RMI(Remote Method Invocation,遠程方法調用)。從 1.4 版本開始,已在 java.beans
包中添加了支持所有 JavaBeansTM 長期存儲的功能。請參閱 XMLEncoder
。
- 另請參見:
-
java.util.Timer
從上面實例+解釋可以很容易學會timer的調用。
看完上面的,也有了一個初步的了解,當注冊一個timer對象以后,如果開發者令其start,那么這個定時器就會每隔設定的delay去調用開發者寫的actionPerformed方法。也就是說,這個計時器本身就是一個線程,這個線程每隔一定時間去調用監聽函數。利用這一性質,就可以很容易的寫出這個計時器了。感覺自己在看文檔的時候,遇到了一些問題,調用了timer類還在不停的想着用循環來實現這個秒表計時器的計時功能,背道而馳了,導致出現了一些列的資源占用等問題
。最后附上題目以及鄙人寫的代碼:
題目
實現代碼如下:

1 /* 2 * #MainFrame.java文檔 3 */ 4 5 import javax.swing.*; 6 7 public class MainFrame{ 8 public static void main(String[] args){ 9 JFrame frame = new JFrame("秒表"); 10 frame.getContentPane().add(new Time()); 11 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 12 frame.setVisible(true); 13 frame.pack(); 14 } 15 }

1 /* 2 * #Time.java文檔 3 */ 4 import java.awt.*; 5 import javax.swing.*; 6 import javax.swing.Timer; 7 import java.awt.event.*; 8 9 public class Time extends JPanel implements ActionListener{ 10 /** 11 * 反序列化 12 */ 13 private static final long serialVersionUID = 1L; 14 15 //定義三個按鈕 16 private JButton start, stop, reset; 17 18 //定義一個標簽用於顯示 19 private JLabel label; 20 21 //定義一個timer用於計時 22 private Timer timer; 23 24 //flag變量,用於記錄 25 private int flag = 0; 26 27 //時間參數 28 private int hour = 0; 29 private int minute = 0; 30 private int second = 0; 31 32 /* 33 * 構造方法,用於創建計時器對象 34 */ 35 public Time(){ 36 37 setBackground(Color.LIGHT_GRAY); 38 setPreferredSize(new Dimension(800,600)); 39 setLayout(null); 40 41 //數字顯示 42 label = new JLabel("00:00:00"); 43 label.setBounds(240, 120, 400, 80); 44 label.setFont(new java.awt.Font("Dialog", 1, 72)); 45 add(label); 46 47 JPanel p1 = new JPanel(); 48 p1.setBackground(Color.LIGHT_GRAY); 49 p1.setBounds(240, 240, 300, 60); 50 add(p1); 51 52 start = new JButton("Start"); 53 start.setFont(new Font("SAN_SERIF",Font.BOLD,24)); 54 start.setBackground(Color.green); 55 stop = new JButton("Stop"); 56 stop.setFont(new Font("SAN_SERIF",Font.BOLD,24)); 57 stop.setBackground(Color.red); 58 reset = new JButton("Reset"); 59 reset.setFont(new Font("SAN_SERIF",Font.BOLD,24)); 60 reset.setBackground(Color.yellow); 61 62 start.addActionListener(this); 63 stop.addActionListener(this); 64 reset.addActionListener(this); 65 66 p1.add(start); 67 p1.add(stop); 68 p1.add(reset); 69 70 timer = new Timer(1000, this); 71 timer.start(); 72 } 73 74 @Override 75 public void actionPerformed(ActionEvent e) { 76 // TODO Auto-generated method stub 77 if(e.getSource() == reset){// 清除標簽內容 78 timer.stop(); 79 flag = 0; 80 label.setText(resetTime()); 81 System.out.println(hour + ":" + minute + ":" + second); 82 } 83 else if(e.getSource() == start){ 84 flag = 1; 85 label.setText(countTime()); 86 System.out.println(hour + ":" + minute + ":" + second); 87 timer.restart(); 88 } 89 else if(e.getSource() == stop){ 90 timer.stop(); 91 flag = 0; 92 label.setText(stopTime()); 93 System.out.println(hour + ":" + minute + ":" + second); 94 } 95 else if(flag==1 && timer.isRunning()){ 96 label.setText(countTime()); 97 System.out.println(hour + ":" + minute + ":" + second); 98 } 99 else if(flag==0 && !timer.isRunning()){ 100 label.setText(stopTime()); 101 System.out.println(hour + ":" + minute + ":" + second); 102 } 103 104 } 105 106 /* 107 * 計時方法 108 */ 109 public String countTime(){ 110 this.second += 1; 111 if(this.second == 60){ 112 this.minute += 1; 113 this.second = 0; 114 } 115 if(this.minute == 60){ 116 this.minute = 0; 117 this.hour += 1; 118 } 119 120 String str = this.toString(this.hour, this.minute, this.second); 121 return str; 122 } 123 124 /* 125 * 暫停計時方法 126 */ 127 public String stopTime(){ 128 String str = this.toString(this.hour, this.minute, this.second); 129 return str; 130 } 131 132 /* 133 * 重置計時方法 134 */ 135 public String resetTime(){ 136 this.hour=0; 137 this.minute=0; 138 this.second=0; 139 String str = this.toString(this.hour, this.minute, this.second); 140 return str; 141 } 142 143 /* 144 * 顯示時間方法 145 */ 146 public String toString(int hour, int minute, int second){ 147 String str1 = String.format("%02d", this.hour); 148 String str2 = String.format("%02d", this.minute); 149 String str3 = String.format("%02d", this.second); 150 return (str1 + ":" + str2 + ":" + str3); 151 } 152 153 }