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

如何在JFrame中实现点击按钮启动计时器的功能

实现点击按钮启动计时的Java Swing方案

原代码可运行性问题

  • 组件初始化顺序错误:未实例化按钮就尝试添加到容器,会触发空指针异常
  • 冗余窗口声明:Program类本身继承JFrame,额外定义的JFrame成员变量属于冗余代码
  • UI线程阻塞:计时逻辑和Thread.sleep放在主线程运行,会导致界面无响应
  • 绘制逻辑错误:自定义绘制方法调用时机不对,会出现闪屏、重绘后内容消失问题
  • 无计时触发控制:程序启动后直接执行计时逻辑,没有和按钮点击事件绑定

完整可运行实现代码

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.*;

@SuppressWarnings("serial")
public class Program extends JFrame implements ActionListener {
    private JButton button;
    private boolean isTimerRunning = false;
    private int decaseconds = 0;        
    private int seconds = 0;
    private int minutes = 0;
    private int hours = 0;

    public Program() {
        setLayout(new FlowLayout());
        setTitle("计时程序");
        setSize(1200,800);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        // 先实例化按钮再添加到容器
        button = new JButton("点击开始计时");
        button.addActionListener(this);
        add(button);
        
        // 所有组件添加完成后再设置窗口可见
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 仅计时启动后绘制时间文本
        if (isTimerRunning) {
            g.setColor(Color.white);
            g.fillRect(0, 0, 1200, 800);
            g.setColor(Color.blue);
            g.drawString(String.format("%d 小时 : %d 分钟 : %d 秒 : %d 0.01秒", hours, minutes, seconds, decaseconds), 100, 100);
        }
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if (!isTimerRunning) {
            isTimerRunning = true;
            button.setText("计时中");
            button.setEnabled(false);
            // 启动独立子线程执行计时逻辑,避免阻塞UI渲染
            new Thread(() -> {
                while (true) {
                    decaseconds++;
                    if(decaseconds == 100) {
                        decaseconds = 0;
                        seconds++;
                    }
                    if(seconds == 60) {
                        seconds = 0;
                        minutes++;
                    }
                    if(minutes == 60) {
                        minutes = 0;
                        hours++;
                    }
                    
                    System.out.printf("%d 小时 : %d 分钟 : %d 秒 : %d 0.01秒%n", hours, minutes, seconds, decaseconds);
                    // 触发界面重绘
                    repaint();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    public static void main(String[] args) {
        // Swing界面初始化推荐放在事件调度线程执行,避免线程安全问题
        SwingUtilities.invokeLater(Program::new);
    }
}

关键逻辑说明

  1. 新增isTimerRunning状态变量控制计时启停,默认关闭,点击按钮后激活
  2. 修正组件初始化顺序,避免空指针异常,移除冗余的JFrame成员变量
  3. 计时逻辑放在独立子线程运行,不会卡住界面交互
  4. 重写paint方法实现绘制,通过repaint()触发界面更新,避免闪屏
  5. 按钮点击事件中判断状态,仅首次点击时启动计时,同时禁用按钮防止重复触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:57:03