Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
100 views
in Technique[技术] by (71.8m points)

java - Adding resume function to stopwatch

I have programmed a simple stopwatch with three functionalities. First, I have a start button to begin the stopwatch , a pause button to pause the stopwatch and finally a reset button to reset the entire stopwatch.

When I hit the pause button, the stopwatch pauses, say at 10.0 seconds. When I resume the stopwatch (pressing the Start button again), the stopwatch doesn't resume from 10.0 seconds onwards. It resumes from the amount of time I paused and the current time. For example, if I paused for 5 seconds and hit resume, the stopwatch goes from 15.0 seconds onwards.

I am aware there isn't a actual pause function in Swing.Timer. Would there be a way to tackle this so the stopwatch resumes normally?

Any suggestion would be appreciated.

Code:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import javax.swing.Timer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;



public class GuiStopwatch {





    public static void main(String[] args) {
        JFrame frame = new JFrame("Stopwatch");

        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setVisible(true);
          JPanel panel = new JPanel();

          panel.setLayout(null);

          JButton startbtn = new JButton("START");  
          JButton pausebtn = new JButton("PAUSE");
          JButton reset = new JButton("RESET");
          JLabel time = new JLabel("Time shows here");
             panel.add(startbtn);
             panel.add(pausebtn);
            panel.add(reset);
            panel.add(time);
             startbtn.setBounds(50, 150, 100, 35);
             pausebtn.setBounds(50, 200, 100, 35);
             reset.setBounds(50, 250, 100, 35);
             time.setBounds(50, 350, 100, 35);
             time.setBackground(Color.black);
             time.setForeground(Color.red);
             frame.add(panel);



            Timer timer = new Timer(1,new ActionListener() {
                Instant start = Instant.now();
                @Override
                public void actionPerformed(ActionEvent e) {


                    time.setText( Duration.between(start, Instant.now()).getSeconds() +  ":" + Duration.between(start, Instant.now()).getNano() );


                }
            });



             startbtn.addActionListener(new ActionListener() {


                @Override
                public void actionPerformed(ActionEvent e) {





                timer.start();




                }
            });



             pausebtn.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {

                    timer.stop();

                }
            });



             reset.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                time.setText("0:0");

                }
            });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Conceptually, the idea is, you want to keep track of the "total running" of the stop watch, this is, all the total duration it has been active.

There's a number of ways you might achieve this, one might be to simply keep a running total which is only updated when the stop watch is stopped or paused. The "duration" of the stop watch is then a sum of the "current duration" of the "current" cycle and the "total previous" duration

Something like...

public class StopWatch {
    private LocalDateTime startTime;
    private Duration totalRunTime = Duration.ZERO;

    public void start() {
        startTime = LocalDateTime.now();
    }

    public void stop() {
        Duration runTime = Duration.between(startTime, LocalDateTime.now());
        totalRunTime = totalRunTime.plus(runTime);
        startTime = null;
    }

    public void pause() {
        stop();
    }

    public void resume() {
        start();
    }

    public void reset() {
        stop();
        totalRunTime = Duration.ZERO;
    }

    public boolean isRunning() {
        return startTime != null;
    }

    public Duration getDuration() {
        Duration currentDuration = Duration.ZERO;
        currentDuration = currentDuration.plus(totalRunTime);
        if (isRunning()) {
            Duration runTime = Duration.between(startTime, LocalDateTime.now());
            currentDuration = currentDuration.plus(runTime);
        }
        return currentDuration;
    }
}

Okay, so start and stop are essentially the same as pause and resume, but you get the point.

And, a runnable example...

Now, this example runs a Swing Timer constantly, but the StopWatch can paused and resumed at any time, the point is to demonstrate that the StopWatch is actually working correctly ;)

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) throws InterruptedException {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;
        private JButton btn;

        private StopWatch stopWatch = new StopWatch();
        private Timer timer;

        public TestPane() {
            label = new JLabel("...");
            btn = new JButton("Start");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(label, gbc);
            add(btn, gbc);

            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    label.setText(Long.toString(stopWatch.getDuration().getSeconds()));
                }
            });
            timer.start();

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (stopWatch.isRunning()) {
                        stopWatch.pause();
                        btn.setText("Start");
                    } else {
                        stopWatch.resume();
                        btn.setText("Pause");
                    }
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public class StopWatch {
        private LocalDateTime startTime;
        private Duration totalRunTime = Duration.ZERO;

        public void start() {
            startTime = LocalDateTime.now();
        }

        public void stop() {
            Duration runTime = Duration.between(startTime, LocalDateTime.now());
            totalRunTime = totalRunTime.plus(runTime);
            startTime = null;
        }

        public void pause() {
            stop();
        }

        public void resume() {
            start();
        }

        public void reset() {
            stop();
            totalRunTime = Duration.ZERO;
        }

        public boolean isRunning() {
            return startTime != null;
        }

        public Duration getDuration() {
            Duration currentDuration = Duration.ZERO;
            currentDuration = currentDuration.plus(totalRunTime);
            if (isRunning()) {
                Duration runTime = Duration.between(startTime, LocalDateTime.now());
                currentDuration = currentDuration.plus(runTime);
            }
            return currentDuration;
        }
    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...