Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a count up timer in java (seconds and milliseconds only)

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.

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:

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();
        }
    });
  }
}
like image 466
user2144555 Avatar asked Jan 27 '26 04:01

user2144555


1 Answers

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:

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();
            }
        });
    }
}
like image 193
K Boden Avatar answered Jan 28 '26 21:01

K Boden



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!