开发者

Stop a stopwatch

开发者 https://www.devze.com 2022-12-26 04:46 出处:网络
I have the following code in a JPanel class which is added to a another class (JFrame). What I\'m trying to implement is some sort of a stopwatch program.

I have the following code in a JPanel class which is added to a another class (JFrame). What I'm trying to implement is some sort of a stopwatch program.

startBtn.addActionListener(new startListener());

class startListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        Timer time = new Timer();
        time.scheduleAtFixedRate(new Stopwatch(), 1000, 1000);
    }
}

This is another class which basically the task.

public class Stopwatch extends TimerTask {

    private final double start = System.currentTimeMillis();

    public void run() {
        double curr = System.currentTimeMillis();
        System.out.println((curr - start) / 1000);
    }
}

The timer works fine and this is definitely far from开发者_如何学编程 complete but I'm not sure how to code the stop button which should stop the timer. Any advice on this? BTW I'm using java.util.timer

EDIT: I want to be able to start it again after stopping it (without the timer being reset)


You can either cancel the entire Timer by calling Timer.cancel(), or you can cancel individual tasks by calling TimerTask.cancel().

Either way, you'll need to keep a reference to the timer and/or task instance when you create it, so that your stop routine can call the appropriate cancel method.

Update:

So you effectively want to be able to pause the timer? I don't think this is supported by the standard interface in java.util.Timer. You could do this by adding a pause() method (or similar) to your custom task, recording the elapsed time up to that point, and restarting the counting when the start button is clicked again. Note that using this technique, you wouldn't stop the timer task itself until you're finished with it completely. It still runs in the background, but you only do anything with it when the stopwatch has been started and is "running" (ie. some kind of flag to indicate the stopwatch's state).

A couple of notes:

  • java.util.Timer runs on a non-EDT thread, so if you're interacting with member variables in both the timer and in Swing action events, you'll need to appropriately handle the implications of multiple threads. It might be worth investigating javax.swing.Timer, which will fire events on the EDT.

  • Also, if you want a super-duper accurate stopwatch, you might consider using System.nanoTime() rather than currentTimeMillis().


If javax.swing.Timer is an acceptable alternative, as @Ash suggests, here is an example.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;

/** @see http://stackoverflow.com/questions/2576909 */
public class JTimeLabel extends JLabel implements ActionListener {

    private static final String Start = "Start";
    private static final String Stop = "Stop";
    private DecimalFormat df = new DecimalFormat("000.0");
    private Timer timer = new javax.swing.Timer(100, this);
    private long now = System.currentTimeMillis();

    public JTimeLabel() {
        this.setHorizontalAlignment(JLabel.CENTER);
        this.setText(when());
    }

    public void actionPerformed(ActionEvent ae) {
        setText(when());
    }

    public void start() {
        timer.start();
    }

    public void stop() {
        timer.stop();
    }

    private String when() {
        return df.format((System.currentTimeMillis() - now) / 1000d);
    }

    private static void create() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JTimeLabel jtl = new JTimeLabel();
        jtl.setFont(new Font("Dialog", Font.BOLD, 32));
        f.add(jtl, BorderLayout.CENTER);

        final JButton button = new JButton(Stop);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String cmd = e.getActionCommand();
                if (Stop.equals(cmd)) {
                    jtl.stop();
                    button.setText(Start);
                } else {
                    jtl.start();
                    button.setText(Stop);
                }

            }
        });
        f.add(button, BorderLayout.SOUTH);
        f.pack();
        f.setVisible(true);
        jtl.start();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                create();
            }
        });
    }
}


I changed the trashgod's source.

update:

  • pause function
  • reset function

public class StopWatch extends JLabel implements ActionListener {
    private static final String Start = "Start";
    private static final String Pause = "Pause";
    private static final String Reset = "Reset";
    private boolean isRunning;
    private Timer timer = new javax.swing.Timer(100, this);
    private long initTime = System.currentTimeMillis();
    private long startTime;
    private long pauseTime;

    public StopWatch() {
        this.setHorizontalAlignment(JLabel.CENTER);
        this.setText(getCurrentTime(System.currentTimeMillis() - initTime));
    }

    public void actionPerformed(ActionEvent ae) {
        setText(getCurrentTime(System.currentTimeMillis() - startTime));
    }

    public void start() {
        if (isRunning == false) {
            startTime = System.currentTimeMillis();
        } else {
            startTime = System.currentTimeMillis() - (pauseTime - startTime);
        }

        isRunning = true;
        timer.start();
    }

    public void pause() {           
        pauseTime = System.currentTimeMillis();
        timer.stop();
    }

    public void reset() {       
        startTime = 0;
        isRunning = false;
        this.setText(getCurrentTime(System.currentTimeMillis() - System.currentTimeMillis()));
    }

    private String getCurrentTime(long time) {
        return myFormat(time);
    }

    private String myFormat(final long time) {
        final long hr = TimeUnit.MILLISECONDS.toHours(time);
        final long min = TimeUnit.MILLISECONDS.toMinutes(time
                - TimeUnit.HOURS.toMillis(hr));
        final long sec = TimeUnit.MILLISECONDS.toSeconds(time
                - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
        final long ms = TimeUnit.MILLISECONDS.toMillis(time
                - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min)
                - TimeUnit.SECONDS.toMillis(sec));
        return String.format("%02d:%02d:%02d.%01d", hr, min, sec, ms/100);
    }

    private static void create() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final StopWatch textLabel = new StopWatch();
        textLabel.setFont(new Font("Dialog", Font.BOLD, 32));
        f.add(textLabel, BorderLayout.CENTER);

        final JButton button = new JButton(Start);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String cmd = e.getActionCommand();
                if (Pause.equals(cmd)) {
                    textLabel.pause();
                    button.setText(Start);
                } else {
                    textLabel.start();
                    button.setText(Pause);
                }
            }
        });

        final JButton button2 = new JButton(Reset);
        button2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                textLabel.reset();
            }
        });

        f.add(button, BorderLayout.SOUTH);
        f.add(button2, BorderLayout.NORTH);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                create();
            }
        });
    }
}


long startTime = System.currentTimeMillis();
    Timer timer = new Timer(100,new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            long elapsedTime = System.currentTimeMillis()-startTime;
            long mil = elapsedTime%1000;
            long sec = elapsedTime/1000%60;
            long min = elapsedTime/60000%60;
            long hr = elapsedTime/3600000;
            label.setText(String.format("%02d:%02d:%02d.%03d", hr,min,sec,mil));
        }
    });
    timer.start();
0

精彩评论

暂无评论...
验证码 换一张
取 消