Проблема сброса таймера обратного отсчета Java - PullRequest
0 голосов
/ 12 ноября 2018

Я кодировал таймер обратного отсчета в Java. Он отсчитывает от любого числа, которое пользователь выбирает в поле со списком, их 3 (час, минута, секунда). Эта часть работает отлично.

Проблема возникает, когда я нажимаю кнопку «Сброс». Он очищает метки, которые я использую для отображения оставшегося времени, и заставляет их отображать «00». Но когда я снова нажимаю «Старт», он вспоминает, где он был в прошлые секунды, и начинает там.

Пожалуйста, помогите !!

Вот мой код для таймера:

private void JButtonActionPerformed(java.awt.event.ActionEvent evt) {                                        

    timer = new Timer(1000, new ActionListener(){


        @Override
        public void actionPerformed(ActionEvent e){

        onoff = true; 


        if(hours == 1 && min == 0 && sec ==0){

            repaint();
            hours--;
            lblHours.setText("00");
            min=59;
            sec=60;

        }

         if(sec == 0 && min <= 59 && min>0){   

             sec=60;
             min--;
             lblHours.setText("00");

         }

         if(sec == 0 && hours == 0 && min<=0){

             repaint();
             JOptionPane.showMessageDialog(rootPane, "You have run out of time and did not manage to escape!", "Time is up!!", 0 );
             hours = 0; min = 0; sec = 0;
             timer.stop();
         }

         else{

             sec--;
             repaint();

             if (sec<10){

             lblSeconds.setText("0"+sec);
             repaint();
             flag = false;

             }
             if (hours==0){

                 repaint();
                 lblHours.setText("00");

             if (min<10)

                 repaint();
                 lblMinutes.setText("0"+min);

                 if (sec<10)

                     lblSeconds.setText("0"+sec);

                 else

                     lblSeconds.setText(""+sec);


             }
             if(flag){
             lblHours.setText(""+hours);
             lblMinutes.setText(""+min);
             lblSeconds.setText(""+sec);
             repaint();

             }


         }
    }

});

    timer.start();


} 

А мой код для кнопки сброса здесь:

    onoff =false;


    timer.stop();
    repaint();

    lblHours.setText("00");
    lblMinutes.setText("00");
    lblSeconds.setText("00");
    repaint();

Я знаю, что немного схожу с ума от перекраски (); но я понятия не имею, как часто я собираюсь его использовать.

Любая помощь / руководство будет принята с благодарностью.

1 Ответ

0 голосов
/ 12 ноября 2018

Нет, где у вас есть доступ, вне контекста, код, вы сбрасываете переменные hours, min, second.

Эту проблему можно решить, просто вставив несколько операторов печати вокруг ваших данных и, возможно, простую настольную проверку ваших состояний.

Сказав это, это какой-то наивный подход.

Swing Timer (и даже Thread.sleep) гарантируют только «как минимум» продолжительность.

Хорошо, значит, вы не разрабатываете таймер сверхвысокого разрешения, но вам все равно нужно понимать, что это может вызвать «дрейф», особенно в течение длительного периода времени.

«Лучшим» решением было бы рассчитать время, прошедшее с момента запуска таймера. К счастью для нас, Java теперь включает в себя большую поддержку для этого в виде более нового API даты / времени.

В следующем примере используется простая концепция «секундомера», которая представляет собой просто количество времени, прошедшее с момента его запуска. Само по себе это не актуально, что делает его очень эффективным.

Но как вам могут помочь часы, движущиеся вперед? Много на самом деле. Вы можете рассчитать оставшееся время, но вычтя желаемое время выполнения из текущего количества прошедшего времени (с момента его запуска), и у вас будет обратный отсчет. Простой.

import java.awt.Dimension;
import java.awt.EventQueue;
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.Instant;
import java.time.temporal.ChronoUnit;
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 class StopWatch {

    private Instant startTime;
    private Duration totalRunTime = Duration.ZERO;

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

    public void stop() {
      Duration runTime = Duration.between(startTime, Instant.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, Instant.now());
        currentDuration = currentDuration.plus(runTime);
      }
      return currentDuration;
    }
  }

  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) {
          Duration runningTime = Duration.of(10, ChronoUnit.MINUTES);
          Duration remainingTime = runningTime.minus(stopWatch.getDuration());
          System.out.println("RemainingTime = " + remainingTime);
          if (remainingTime.isZero() || remainingTime.isNegative()) {
            timer.stop();
            label.setText("0hrs 0mins 0secs");
          } else {
            long hours = remainingTime.toHours();
            long mins = remainingTime.toMinutesPart();
            long secs = remainingTime.toSecondsPart();
            label.setText(String.format("%dhrs %02dmins %02dsecs", hours, mins, secs));
          }
        }
      });
      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);
    }

  }

}
...