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

Java Swing打砖块游戏PaintComponent()方法第二次运行后卡住求助

问题排查与修复方案

致命错误:绘制方法调用参数不匹配

你在MyPanel的全局绘制方法中错误传入了不存在的变量g,你定义的所有绘制重载方法均只接收2个参数,调用时多传的g是paintComponent的局部变量,静态方法无法访问,直接导致绘制线程卡死:

// 错误写法
public static void draw(Graphics2D g2){
    draw(g2, g, model.getPaddle());
    draw(g2, g, model.getBall());
    draw(g2, g, model.getBrickArray());
}

修正为匹配重载方法的参数:

// 正确写法
public static void draw(Graphics2D g2){
    draw(g2, model.getPaddle());
    draw(g2, model.getBall());
    draw(g2, model.getBrickArray());
}

其他可引发卡顿的问题

  • 静态变量线程安全问题:Model被定义为静态变量,你在非EDT线程修改模型属性、在EDT线程读取模型属性,没有同步措施会出现数据可见性问题,引发绘制异常。移除所有不必要的static修饰符,将model改为实例变量即可。
  • Swing组件定义冗余:View类本身继承了JFrame,内部又重新定义了一个JFrame实例frame,你实际显示的是内部的frame,updateView中调用的revalidate()是外层未显示的View实例的方法,无法生效。直接删除View类的JFrame继承即可,updateView中不需要调用revalidate()。
  • 游戏循环实现错误:你在Controller构造方法中直接循环提交更新任务,会一次性提交10个任务到EDT队列,后续如果改成无限循环会直接阻塞EDT线程。改用javax.swing.Timer实现游戏主循环,保证所有更新操作都在EDT线程执行,避免线程安全问题:
    public Controller(Model model, View view){
        this.model = model;
        this.view = view;
        initView();
        // 16ms刷新一次,约60帧
        new Timer(16, e -> {
            model.getBrickArray()[0].setDestroyed(true);
            doCycle();
        }).start();
    }
    
  • 绘制逻辑冗余:销毁砖块时不需要调用clearRect,你已经设置面板背景为黑色,直接跳过绘制已销毁的砖块即可,避免多余的绘制操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:27:04