如何在点击按钮时为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"); } }); } }
关键修改点说明
- 新增成员变量:把
timer、startTime和timeLabel改成类成员,这样各个监听器都能访问到它们,避免局部变量的生命周期问题。 - 计时逻辑替换:不再获取系统当前时间,而是计算
当前时间 - 起始时间得到已流逝的毫秒数,再转换成时分秒。 - 格式化优化:用
String.format("%02d", ...)确保每个时间单位都是两位数字(比如01秒而不是1秒)。 - 补全按钮功能:给Stop和Reset按钮加上了对应的停止、重置逻辑,让秒表完整可用。
- Timer间隔调整:把Timer的触发间隔从1毫秒改成1000毫秒(1秒),因为秒表每秒更新一次就足够了,太频繁会浪费资源。
小提示
另外,Swing中不推荐用setLayout(null)这种绝对布局,建议用BorderLayout、FlowLayout或者GridBagLayout来管理组件位置,这样窗口大小变化时组件能自动调整位置,体验更好~
内容的提问来源于stack exchange,提问作者Lord Jesus
相关产品推荐
相关产品推荐

