【问题标题】:Adding resume function to stopwatch为秒表添加恢复功能
【发布时间】:2018-05-18 09:57:18
【问题描述】:

我编写了一个具有三个功能的简单秒表。首先,我有一个启动秒表的开始按钮,一个暂停秒表的暂停按钮,最后一个重置整个秒表的重置按钮。

当我按下暂停按钮时,秒表会暂停,比如 10.0 秒。当我恢复秒表(再次按下开始按钮)时,秒表不会从 10.0 秒开始恢复。它从我暂停的时间和当前时间恢复。例如,如果我暂停 5 秒并点击恢复,秒表会从 15.0 秒开始。

我知道Swing.Timer 中没有实际的暂停功能。有没有办法解决这个问题,让秒表恢复正常?

任何建议都将不胜感激。

代码:

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");

                }
            });

【问题讨论】:

  • 所以,“基本”概念是 - 您需要跟踪秒表的总损坏时间,即从它第一次启动到它暂停的时间。恢复后,您会将“新运行”时间添加到之前的计数中
  • panel.setLayout(null);

标签: java swing


【解决方案1】:

从概念上讲,这个想法是,您想要跟踪秒表的“总运行时间”,即它一直处于活动状态的所有总持续时间。

您可以通过多种方式实现此目的,其中一种可能是简单地保持运行总计,该运行总计仅在秒表停止或暂停时更新。那么秒表的“持续时间”就是“当前”周期的“当前持续时间”和“之前的总持续时间”的总和

类似...

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;
    }
}

好的,所以startstoppauseresume 基本相同,但你明白了。

还有,一个可运行的例子……

现在,这个例子不断地运行一个Swing Timer,但是StopWatch 可以在任何时候pausedresumed,关键是要证明StopWatch 实际上是正常工作的;)

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;
        }
    }

}

【讨论】:

  • 所以,Instant.now() 在我的情况下并不理想,而不是与使用 LocalDateTime.now() 相比?
  • @LordJesus 说实话,我只知道如何处理LocalDateTime :P
  • @LordJesus 做了一个快速检查,将LocalDateTime 替换为Instant,似乎工作正常
  • 我明白了。您的解决方案很好,但编写的代码比我的要多得多。我想跟踪“运行”时间,这可能是最好的方法吗?
  • 我也在比较你的解决方案和我的解决方案。我想不同之处在于您添加了更多逻辑代码来跟踪时间,然后在单击恢复时,将其添加回之前的计数。我说的对吗?
猜你喜欢
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 2012-04-24
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
相关资源
最近更新 更多