本文所述实例可以实现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。