java 在java中创建一个计数计时器(仅限秒和毫秒)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16815724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create a count up timer in java (seconds and milliseconds only)
提问by user2144555
I'm doing a count up timer in java. I found the following example: Creating a Count Up timer to Break in java, and that's working fine. But I want to show the time in the format "mm:ss:SSS", because I want to measure really small time responses. So, when it reaches the 1000 msec, it is 1 second.
我正在用 java做一个计数计时器。我找到了以下示例:在 java 中创建一个倒数计时器以中断,并且工作正常。但我想以"mm:ss:SSS" 格式显示时间,因为我想测量非常小的时间响应。所以,当它达到 1000 毫秒时,就是 1 秒。
I made some changes, but I can't present the time in the pretended format. The numbers start to appear were the seconds should be, and not in the milliseconds.
我做了一些更改,但我无法以假装格式显示时间。数字开始出现应该是秒,而不是毫秒。
If you have a better example that the one that I'm following, it's fine.
如果你有一个更好的例子,我正在关注的那个,那很好。
Edit:It is better, but it is not working fine yet. It is counting too slow (1 minute here correspond to 2 real minutes). My code is here:
编辑:它更好,但还不能正常工作。计数太慢(这里的 1 分钟对应于实际的 2 分钟)。我的代码在这里:
public class Counter extends JFrame {
private static final String stop = "Stop";
private static final String start = "Start";
private final ClockListener clock = new ClockListener();
private final Timer timer = new Timer(1, clock);
private final JTextField tf = new JTextField(9);
public Counter()
{
timer.setInitialDelay(0);
JPanel panel = new JPanel();
tf.setHorizontalAlignment(JTextField.RIGHT);
tf.setEditable(false);
panel.add(tf);
final JToggleButton b = new JToggleButton(start);
b.addItemListener(new ItemListener()
{
@Override
public void itemStateChanged(ItemEvent e)
{
if (b.isSelected())
{
timer.start();
b.setText(stop);
}
else
{
timer.stop();
b.setText(start);
}
}
});
panel.add(b);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.setTitle("Timer");
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private class ClockListener implements ActionListener
{
private int minutes;
private int seconds;
private int milliseconds;
@Override
public void actionPerformed(ActionEvent e)
{
SimpleDateFormat date = new SimpleDateFormat("mm.ss.SSS");
if (milliseconds == 1000)
{
milliseconds = 000;
seconds++;
}
if (seconds == 60) {
seconds = 00;
minutes++;
}
tf.setText(String.valueOf(minutes + ":" + seconds + ":" + milliseconds));
milliseconds++;
}
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run() {
Counter clock = new Counter();
clock.start();
}
});
}
}
回答by K Boden
You are counting and relying on the timer to expire in exactly 1 millisecond. The timer (actually the OS) doesn't guarantee that exactly and only 1 millisecond will happen before the expiration, and the code you are running upon expiration takes some time too. Instead, use the timer just to trigger the refresh. I chose 53ms, as it gives the user a fuzzy feeling that the milliseconds are flying by, but notice that the timer updates 1 final time after the user clicks stop, which does not have to be at a multiple of 53ms. The time that gets displayed is not related to the number of Timer expirations, only to the start time that was recorded when the user pressed Start and the current System time:
您正在计数并依赖计时器在 1 毫秒内到期。计时器(实际上是操作系统)并不能保证在到期前准确且只有 1 毫秒会发生,并且您在到期时运行的代码也需要一些时间。相反,使用计时器只是为了触发刷新。我选择了 53ms,因为它让用户有一种毫秒在飞逝的模糊感觉,但请注意,计时器在用户单击停止后更新 1 次最后一次,这不一定是 53ms 的倍数。显示的时间与 Timer 过期次数无关,仅与用户按下 Start 时记录的开始时间和当前 System time 相关:
public class Counter extends JFrame {
private static final String stop = "Stop";
private static final String start = "Start";
private final ClockListener clock = new ClockListener();
private final Timer timer = new Timer(53, clock);
private final JTextField tf = new JTextField(9);
private final SimpleDateFormat date = new SimpleDateFormat("mm.ss.SSS");
private long startTime;
public Counter() {
timer.setInitialDelay(0);
JPanel panel = new JPanel();
tf.setHorizontalAlignment(JTextField.RIGHT);
tf.setEditable(false);
panel.add(tf);
final JToggleButton b = new JToggleButton(start);
b.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (b.isSelected()) {
startTime = System.currentTimeMillis();
timer.start();
b.setText(stop);
}
else {
updateClock();
startTime = 0;
timer.stop();
b.setText(start);
}
}
});
panel.add(b);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.setTitle("Timer");
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private void updateClock() {
Date elapsed = new Date(System.currentTimeMillis() - startTime);
tf.setText(date.format(elapsed));
}
private class ClockListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
updateClock();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Counter clock = new Counter();
}
});
}
}