You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java GUI秒表:实现HH:mm:ss格式显示及修复重置按钮失效问题

解决Java GUI秒表的两个问题:格式转换与重置失效

我来帮你搞定这两个问题,先拆解核心问题,再一步步修改代码:

一、重置按钮失效的原因及解决

你现在的问题出在Timer对象的作用域上:

  • 每次点击START按钮时,你都在监听器内部新建了一个Timer局部变量,这个变量只在当前方法里有效,外部的RESET监听器根本访问不到它。
  • 而RESET监听器里又新建了一个完全无关的Timer,调用它的stop()当然对正在运行的计时器没有任何作用。

解决办法:把Timer提升为类的成员变量,让所有监听器都能操作同一个实例。

二、将计时格式改为HH:mm:ss

当前直接拼接秒和纳秒的方式不符合需求,我们需要:

  1. 计算从开始到现在的总秒数
  2. 将总秒数拆分为小时、分钟、剩余秒数
  3. 使用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
            }
        });
    }
}

关键修改点说明

  1. Timer作用域调整:把Timer和startTime设为类静态成员,确保所有监听器操作的是同一个实例。
  2. 格式优化:用String.format("%02d:%02d:%02d", hours, minutes, seconds)实现两位数字的HH:mm:ss格式,%02d表示不足两位时补零。
  3. 性能优化:把Timer的间隔从1毫秒改成1000毫秒(1秒),因为我们只需要每秒更新一次时间,1毫秒的间隔会占用过多CPU资源。
  4. 补充STOP按钮功能:你之前的代码里STOP按钮没有实现监听器,我帮你补上了,点击可以暂停计时。
  5. 组件加载优化:把frame.setVisible(true)放在最后,避免组件还没完全加载就显示导致的布局异常。

如果你希望重置后显示为"0:0"而不是"00:00:00",只需要把重置时的文本改成timeLabel.setText("0:0"),同时调整START里的格式化逻辑即可,但HH:mm:ss格式更符合标准秒表的显示习惯。

内容的提问来源于stack exchange,提问作者Lord Jesus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:16:47