倒数计时器,将秒数显示到 JLabel 中时出错
Countdown timer, error in displaying the seconds into JLabel
我无法在标签中显示秒数。每当我 运行 代码时,它应该是“9(分钟):59(秒)”,但它没有按计划进行,而是只显示 9 分钟。
注意:我只用了一个标签来显示分秒计时器。
代码如下:
我用了方法。
private void countDown() {
tmClock = new Timer();
NumberFormat nbFormat = new DecimalFormat("00");
if (minutes == 0 && seconds == 0) {
JOptionPane.showMessageDialog(null, "time's up!");
tmClock.cancel();
new Result().setVisible(true);
this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
}
lblTime.setText(nbFormat.format(minutes) + ":" );
String format = nbFormat.format(seconds);
tmClock.schedule(new TimerTask() {
@Override
public void run() {
seconds--;
countDown();
}
}, 1000);
}
这里有很多问题:
- 您使用了错误的计时器 class。这是一个 Swing 应用程序,执行此操作的线程安全方法是使用
javax.swing.Timer
,而不是 java.util.Timer
- 您在 TimerTask 中调用
countDown()
,并且几乎以递归方式向 Timer 对象错误地添加了新的 TimerTask。请注意,您甚至不应该再次使用 java.util.TimerTask
,因为这是一个 Swing 应用程序。
解决方案:
- 改用 Swing Timer。
- 在计时器的 ActionListener 中,更新您的秒值,然后设置 JLabel 的文本。
例如,
// declaration section, create the Swing Timer
private int timerDelay = 1000; // msecs
private Timer myTimer = new Timer(timerDelay, e -> countDown());
// perhaps in a constructor or button's ActionListener, start the Timer
myTimer.start();
private void countDown() {
// seconds--; // update seconds
if (minutes == 0 && seconds == 0) {
myTimer.stop(); // stop the Timer if time's up
JOptionPane.showMessageDialog(null, "time's up!");
new Result().setVisible(true);
this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--;
}
// create label's text and update JLabel
String text = String.format("%02d:%02d", minutes, seconds);
lblTime.setText(text);
}
工作示例:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestTimer extends JPanel {
private static final String FORMAT_TXT = "%02d:%02d";
private int seconds = 0;
private int minutes = 10;
private JLabel lblTime = new JLabel(String.format(FORMAT_TXT, minutes, seconds));
private int timerDelay = 1000; // msecs
private Timer myTimer = new Timer(timerDelay, e -> countDown());
public TestTimer() {
lblTime.setHorizontalAlignment(SwingConstants.CENTER);
setLayout(new BorderLayout());
add(lblTime, BorderLayout.PAGE_START);
add(new JButton(new AbstractAction("Start") {
@Override
public void actionPerformed(ActionEvent e) {
if (myTimer != null && !myTimer.isRunning()) {
myTimer.start();
}
}
}));
}
private void countDown() {
if (minutes == 0 && seconds == 0) {
if (myTimer != null && myTimer.isRunning()) {
myTimer.stop(); // stop the Timer if time's up
}
JOptionPane.showMessageDialog(this, "time's up!");
// new Result().setVisible(true);
// this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--; // update seconds
}
// create label's text and update JLabel
String text = String.format("%02d:%02d", minutes, seconds);
lblTime.setText(text);
}
private static void createAndShowGui() {
TestTimer mainPanel = new TestTimer();
JFrame frame = new JFrame("Test Timer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
我无法在标签中显示秒数。每当我 运行 代码时,它应该是“9(分钟):59(秒)”,但它没有按计划进行,而是只显示 9 分钟。
注意:我只用了一个标签来显示分秒计时器。
代码如下: 我用了方法。
private void countDown() {
tmClock = new Timer();
NumberFormat nbFormat = new DecimalFormat("00");
if (minutes == 0 && seconds == 0) {
JOptionPane.showMessageDialog(null, "time's up!");
tmClock.cancel();
new Result().setVisible(true);
this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
}
lblTime.setText(nbFormat.format(minutes) + ":" );
String format = nbFormat.format(seconds);
tmClock.schedule(new TimerTask() {
@Override
public void run() {
seconds--;
countDown();
}
}, 1000);
}
这里有很多问题:
- 您使用了错误的计时器 class。这是一个 Swing 应用程序,执行此操作的线程安全方法是使用
javax.swing.Timer
,而不是java.util.Timer
- 您在 TimerTask 中调用
countDown()
,并且几乎以递归方式向 Timer 对象错误地添加了新的 TimerTask。请注意,您甚至不应该再次使用java.util.TimerTask
,因为这是一个 Swing 应用程序。
解决方案:
- 改用 Swing Timer。
- 在计时器的 ActionListener 中,更新您的秒值,然后设置 JLabel 的文本。
例如,
// declaration section, create the Swing Timer
private int timerDelay = 1000; // msecs
private Timer myTimer = new Timer(timerDelay, e -> countDown());
// perhaps in a constructor or button's ActionListener, start the Timer
myTimer.start();
private void countDown() {
// seconds--; // update seconds
if (minutes == 0 && seconds == 0) {
myTimer.stop(); // stop the Timer if time's up
JOptionPane.showMessageDialog(null, "time's up!");
new Result().setVisible(true);
this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--;
}
// create label's text and update JLabel
String text = String.format("%02d:%02d", minutes, seconds);
lblTime.setText(text);
}
工作示例:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestTimer extends JPanel {
private static final String FORMAT_TXT = "%02d:%02d";
private int seconds = 0;
private int minutes = 10;
private JLabel lblTime = new JLabel(String.format(FORMAT_TXT, minutes, seconds));
private int timerDelay = 1000; // msecs
private Timer myTimer = new Timer(timerDelay, e -> countDown());
public TestTimer() {
lblTime.setHorizontalAlignment(SwingConstants.CENTER);
setLayout(new BorderLayout());
add(lblTime, BorderLayout.PAGE_START);
add(new JButton(new AbstractAction("Start") {
@Override
public void actionPerformed(ActionEvent e) {
if (myTimer != null && !myTimer.isRunning()) {
myTimer.start();
}
}
}));
}
private void countDown() {
if (minutes == 0 && seconds == 0) {
if (myTimer != null && myTimer.isRunning()) {
myTimer.stop(); // stop the Timer if time's up
}
JOptionPane.showMessageDialog(this, "time's up!");
// new Result().setVisible(true);
// this.dispose();
} else if (seconds == 0) {
minutes--;
seconds = 59;
} else {
seconds--; // update seconds
}
// create label's text and update JLabel
String text = String.format("%02d:%02d", minutes, seconds);
lblTime.setText(text);
}
private static void createAndShowGui() {
TestTimer mainPanel = new TestTimer();
JFrame frame = new JFrame("Test Timer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}