【问题标题】:Stop a stopwatch停止秒表
【发布时间】:2017-12-08 18:52:06
【问题描述】:

我在一个 JPanel 类中有以下代码,它被添加到另一个类 (JFrame) 中。我正在尝试实现的是某种秒表程序。

startBtn.addActionListener(new startListener());

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

这是另一个基本任务的类。

public class Stopwatch extends TimerTask {

    private final double start = System.currentTimeMillis();

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

计时器工作正常,这肯定远未完成,但我不确定如何编写应该停止计时器的停止按钮。对此有何建议?顺便说一句,我正在使用 java.util.timer

编辑:我希望能够在停止后再次启动它(不重置计时器)

【问题讨论】:

    标签: java timer


    【解决方案1】:

    您可以通过调用Timer.cancel() 来取消整个Timer,也可以通过调用TimerTask.cancel() 来取消单个任务。

    无论哪种方式,您都需要在创建计时器和/或任务实例时保留对它的引用,以便您的停止例程可以调用适当的取消方法。

    更新:

    所以您实际上希望能够暂停计时器?我认为java.util.Timer 中的标准接口不支持这一点。您可以通过将pause() 方法(或类似方法)添加到您的自定义任务,记录到该点所用的时间,并在再次单击开始按钮时重新开始计数来实现此目的。请注意,使用此技术,您不会停止计时器任务本身,直到您完全完成它。它仍然在后台运行,但只有在秒表已启动并且“正在运行”(即某种指示秒表状态的标志)时才对它进行任何操作。

    几点说明:

    • java.util.Timer 在非 EDT 线程上运行,因此如果您在计时器和 Swing 操作事件中都与成员变量进行交互,则需要适当地处理多线程的影响。可能值得研究 javax.swing.Timer,它会在 EDT 上触发事件。

    • 另外,如果您想要一个超级精确的秒表,您可以考虑使用System.nanoTime() 而不是currentTimeMillis()

    【讨论】:

    • 抱歉,这不是我想要的。我编辑了我的问题。
    【解决方案2】:

    如果javax.swing.Timer 是可接受的替代方案,正如@Ash 建议的那样,这里有一个示例。

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

    【讨论】:

      【解决方案3】:

      我更改了垃圾神的来源。

      更新:

      • 暂停功能
      • 复位功能

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

      【讨论】:

        【解决方案4】:
        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();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多