Нет, где у вас есть доступ, вне контекста, код, вы сбрасываете переменные 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);
}
}
}