Java GUI秒表:实现HH:mm:ss格式显示及修复重置按钮失效问题
解决Java GUI秒表的两个问题:格式转换与重置失效
我来帮你搞定这两个问题,先拆解核心问题,再一步步修改代码:
一、重置按钮失效的原因及解决
你现在的问题出在Timer对象的作用域上:
- 每次点击START按钮时,你都在监听器内部新建了一个
Timer局部变量,这个变量只在当前方法里有效,外部的RESET监听器根本访问不到它。 - 而RESET监听器里又新建了一个完全无关的
Timer,调用它的stop()当然对正在运行的计时器没有任何作用。
解决办法:把Timer提升为类的成员变量,让所有监听器都能操作同一个实例。
二、将计时格式改为HH:mm:ss
当前直接拼接秒和纳秒的方式不符合需求,我们需要:
- 计算从开始到现在的总秒数
- 将总秒数拆分为小时、分钟、剩余秒数
- 使用
String.format()格式化每个部分,确保补零(比如把1秒变成01秒)
修改后的完整代码
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.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer; public class GuiStopwatch { // 将Timer声明为类静态成员,让所有监听器都能访问 private static Timer timer; // 记录计时开始的时间 private static Instant startTime; public static void main(String[] args) { JFrame frame = new JFrame("Stopwatch"); frame.setSize(500, 500); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(); panel.setLayout(null); JButton startBtn = new JButton("START"); JButton stopBtn = new JButton("STOP"); JButton resetBtn = new JButton("RESET"); JLabel timeLabel = new JLabel("00:00:00"); panel.add(startBtn); panel.add(stopBtn); panel.add(resetBtn); panel.add(timeLabel); startBtn.setBounds(50, 150, 100, 35); stopBtn.setBounds(50, 200, 100, 35); resetBtn.setBounds(50, 250, 100, 35); timeLabel.setBounds(50, 350, 150, 35); timeLabel.setBackground(Color.black); timeLabel.setForeground(Color.red); timeLabel.setOpaque(true); // 要设置不透明才能显示背景色 frame.add(panel); frame.setVisible(true); // 建议最后设置可见,避免组件加载异常 // START按钮监听器 startBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 如果计时器已经在运行,先停止(避免多次点击启动多个计时器) if (timer != null && timer.isRunning()) { timer.stop(); } startTime = Instant.now(); // 初始化Timer,每1000毫秒更新一次(没必要1毫秒,太耗资源) timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Duration elapsed = Duration.between(startTime, Instant.now()); long totalSeconds = elapsed.getSeconds(); // 拆分总秒数为小时、分钟、秒 long hours = totalSeconds / 3600; long minutes = (totalSeconds % 3600) / 60; long seconds = totalSeconds % 60; // 格式化为HH:mm:ss,自动补零 timeLabel.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds)); } }); timer.start(); } }); // STOP按钮监听器(你之前没实现,这里补上) stopBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (timer != null && timer.isRunning()) { timer.stop(); } } }); // RESET按钮监听器 resetBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 停止计时器(如果正在运行) if (timer != null && timer.isRunning()) { timer.stop(); } // 重置显示文本为初始状态 timeLabel.setText("00:00:00"); // 如果需要重置后可以重新计时,这里不需要额外操作,下次点击START会重新记录startTime } }); } }
关键修改点说明
- Timer作用域调整:把
Timer和startTime设为类静态成员,确保所有监听器操作的是同一个实例。 - 格式优化:用
String.format("%02d:%02d:%02d", hours, minutes, seconds)实现两位数字的HH:mm:ss格式,%02d表示不足两位时补零。 - 性能优化:把Timer的间隔从1毫秒改成1000毫秒(1秒),因为我们只需要每秒更新一次时间,1毫秒的间隔会占用过多CPU资源。
- 补充STOP按钮功能:你之前的代码里STOP按钮没有实现监听器,我帮你补上了,点击可以暂停计时。
- 组件加载优化:把
frame.setVisible(true)放在最后,避免组件还没完全加载就显示导致的布局异常。
如果你希望重置后显示为"0:0"而不是"00:00:00",只需要把重置时的文本改成timeLabel.setText("0:0"),同时调整START里的格式化逻辑即可,但HH:mm:ss格式更符合标准秒表的显示习惯。
内容的提问来源于stack exchange,提问作者Lord Jesus
相关产品推荐
相关产品推荐

