本文所述實例可以實現Java在界面上動態的顯示時間。具體實現方法匯總如下:
1.方法一 用TimerTask:
利用java.util.Timer和java.util.TimerTask來做動態更新,畢竟每次更新可以看作是計時1秒發生一次。
代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
import java.awt.Dimension; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * This class is a simple JFrame implementation to explain how to * display time dynamically on the JSwing-based interface. * @author Edison * */ public class TimeFrame extends JFrame { /* * Variables */ private JPanel timePanel; private JLabel timeLabel; private JLabel displayArea; private String DEFAULT_TIME_FORMAT = "HH:mm:ss"; private String time; private int ONE_SECOND = 1000; public TimeFrame() { timePanel = new JPanel(); timeLabel = new JLabel("CurrentTime: "); displayArea = new JLabel(); configTimeArea(); timePanel.add(timeLabel); timePanel.add(displayArea); this.add(timePanel); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setSize(new Dimension(200,70)); this.setLocationRelativeTo(null); } /** * This method creates a timer task to update the time per second */ private void configTimeArea() { Timer tmr = new Timer(); tmr.scheduleAtFixedRate(new JLabelTimerTask(),new Date(), ONE_SECOND); } /** * Timer task to update the time display area * */ protected class JLabelTimerTask extends TimerTask{ SimpleDateFormat dateFormatter = new SimpleDateFormat(DEFAULT_TIME_FORMAT); @Override public void run() { time = dateFormatter.format(Calendar.getInstance().getTime()); displayArea.setText(time); } } public static void main(String arg[]) { TimeFrame timeFrame= new TimeFrame(); timeFrame.setVisible( true ); } } |
繼承TimerTask來創建一個自定義的task,獲取當前時間,更新displayArea.
然后創建一個timer的實例,每1秒執行一次timertask。由于用schedule可能會有時間誤差產生,所以直接調用精度更高的scheduleAtFixedRate的。
2. 方法二:利用線程:
這個就比較簡單了。具體代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
import java.awt.Dimension; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * This class is a simple JFrame implementation to explain how to * display time dynamically on the JSwing-based interface. * @author Edison * */ public class DTimeFrame2 extends JFrame implements Runnable{ private JFrame frame; private JPanel timePanel; private JLabel timeLabel; private JLabel displayArea; private String DEFAULT_TIME_FORMAT = "HH:mm:ss" ; private int ONE_SECOND = 1000 ; public DTimeFrame2() { timePanel = new JPanel(); timeLabel = new JLabel( "CurrentTime: " ); displayArea = new JLabel(); timePanel.add(timeLabel); timePanel.add(displayArea); this .add(timePanel); this .setDefaultCloseOperation(EXIT_ON_CLOSE); this .setSize( new Dimension( 200 , 70 )); this .setLocationRelativeTo( null ); } public void run() { while ( true ) { SimpleDateFormat dateFormatter = new SimpleDateFormat(DEFAULT_TIME_FORMAT); displayArea.setText(dateFormatter.format( Calendar.getInstance().getTime())); try { Thread.sleep(ONE_SECOND); } catch (Exception e) { displayArea.setText( "Error!!!" ); } } } public static void main(String arg[]) { DTimeFrame2 df2= new DTimeFrame2(); df2.setVisible( true ); Thread thread1= new Thread(df2); thread1.start(); } } |
比較:
個人傾向于方法一,因為Timer是可以被多個TimerTask共用,而產生一個線程,會增加多線程的維護復雜度。
注意如下代碼:
1
2
|
jFrame.setDefaultCloseOperation(); // 給關閉按鈕增加特定行為 jFrame.setLocationRelativeTo( null ); // 讓Frame一出來就在屏幕中間,而不是左上方。 |
將上面方法一稍微一修改,就可以顯示多國時間。代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import java.util.Timer; import java.util.TimerTask; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; /** * A simple world clock * @author Edison * */ public class WorldTimeFrame extends JFrame { /** * */ private static final long serialVersionUID = 4782486524987801209L; private String time; private JPanel timePanel; private TimeZone timeZone; private JComboBox zoneBox; private JLabel displayArea; private int ONE_SECOND = 1000 ; private String DEFAULT_FORMAT = "EEE d MMM, HH:mm:ss" ; public WorldTimeFrame() { zoneBox = new JComboBox(); timePanel = new JPanel(); displayArea = new JLabel(); timeZone = TimeZone.getDefault(); zoneBox.setModel( new DefaultComboBoxModel(TimeZone.getAvailableIDs())); zoneBox.addActionListener( new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { updateTimeZone(TimeZone.getTimeZone((String) zoneBox.getSelectedItem())); } }); configTimeArea(); timePanel.add(displayArea); this .setLayout( new BorderLayout()); this .add(zoneBox, BorderLayout.NORTH); this .add(timePanel, BorderLayout.CENTER); this .setLocationRelativeTo( null ); this .setDefaultCloseOperation(EXIT_ON_CLOSE); this .setVisible( true ); pack(); } /** * This method creates a timer task to update the time per second */ private void configTimeArea() { Timer tmr = new Timer(); tmr.scheduleAtFixedRate( new JLabelTimerTask(), new Date(), ONE_SECOND); } /** * Timer task to update the time display area * */ public class JLabelTimerTask extends TimerTask{ SimpleDateFormat dateFormatter = new SimpleDateFormat(DEFAULT_FORMAT, Locale.ENGLISH); @Override public void run() { dateFormatter.setTimeZone(timeZone); time = dateFormatter.format(Calendar.getInstance().getTime()); displayArea.setText(time); } } /** * Update the timeZone * @param newZone */ public void updateTimeZone(TimeZone newZone) { this .timeZone = newZone; } public static void main(String arg[]) { new WorldTimeFrame(); } } |
本來需要在updateTimeZone(TimeZone newZone)中,更新displayArea的。但是考慮到TimerTask執行的時間太短,才1秒鐘,以肉眼觀察,基本上是和立刻更新沒區別。如果TimerTask執行時間長的話,這里就要立刻重新用心的時間更新一下displayArea。
補充:
①. pack() 用來自動計算屏幕大小;
②. TimeZone.getAvailableIDs() 用來獲取所有的TimeZone。