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

如何在点击按钮时为Java GUI程序添加秒表计时器?

实现Swing秒表的正确姿势

嘿,我懂你的问题——你现在用SimpleDateFormat输出的是系统实时时间,这可不是咱们要的秒表功能!秒表需要从0开始累加计时,而不是显示当前时间。咱们来调整一下代码,实现真正的计时功能:

核心思路

要做秒表,关键是记录计时开始的时刻,然后每次Timer触发时,计算当前时间与起始时刻的差值,再把这个差值转换成HH:mm:ss格式显示出来。另外,咱们还要把Stop和Reset按钮的逻辑补上,不然只有Start可不够用~

修改后的完整代码

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GuiStopwatch {
    // 类成员变量,方便在监听器中访问
    private Timer timer;
    private long startTime; // 记录计时开始的毫秒数
    private JLabel timeLabel;

    public static void main(String[] args) {
        new GuiStopwatch();
    }

    public GuiStopwatch() {
        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");
        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);

        // 初始化Timer,间隔1000毫秒(1秒)触发一次就够了,不用1毫秒
        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 计算已流逝的毫秒数
                long elapsedTime = System.currentTimeMillis() - startTime;
                // 转换成小时、分钟、秒
                long hours = (elapsedTime / 3600000) % 24;
                long minutes = (elapsedTime / 60000) % 60;
                long seconds = (elapsedTime / 1000) % 60;
                // 格式化字符串,补零确保两位数字
                String timeStr = String.format("%02d:%02d:%02d", hours, minutes, seconds);
                timeLabel.setText(timeStr);
            }
        });

        // Start按钮逻辑
        startBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!timer.isRunning()) {
                    // 如果Timer没在运行,记录当前时间作为起始点,然后启动Timer
                    startTime = System.currentTimeMillis();
                    timer.start();
                }
            }
        });

        // Stop按钮逻辑
        stopBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.stop();
            }
        });

        // Reset按钮逻辑
        resetBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                timer.stop();
                timeLabel.setText("00:00:00");
            }
        });
    }
}

关键修改点说明

  1. 新增成员变量:把timer、startTime和timeLabel改成类成员,这样各个监听器都能访问到它们,避免局部变量的生命周期问题。
  2. 计时逻辑替换:不再获取系统当前时间,而是计算当前时间 - 起始时间得到已流逝的毫秒数,再转换成时分秒。
  3. 格式化优化:用String.format("%02d", ...)确保每个时间单位都是两位数字(比如01秒而不是1秒)。
  4. 补全按钮功能:给Stop和Reset按钮加上了对应的停止、重置逻辑,让秒表完整可用。
  5. Timer间隔调整:把Timer的触发间隔从1毫秒改成1000毫秒(1秒),因为秒表每秒更新一次就足够了,太频繁会浪费资源。

小提示

另外,Swing中不推荐用setLayout(null)这种绝对布局,建议用BorderLayout、FlowLayout或者GridBagLayout来管理组件位置,这样窗口大小变化时组件能自动调整位置,体验更好~

内容的提问来源于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 04:21:41