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

Java Swing调用repaint()未触发paint(Graphics)方法执行问题求助

问题核心原因

你遇到的repaint()不触发paint()的核心问题是JFrame实例混淆,除此之外还有不符合Swing绘制规范的问题,具体如下:

  1. 实例调用错误
    你的View类本身已经继承了JFrame,但你在createFrame()方法中又重新创建了一个独立的JFrame对象frame,你调用setVisible()显示的是这个新创建的内部frame对象,而你在updateView()中调用repaint()的主体是当前View类实例,这个实例从未被设置为可见,自然不会触发它的paint()方法。
  2. 绘制逻辑不符合Swing规范
    Swing不推荐直接重写JFrame的paint()方法,JFrame的绘制包含边框、标题栏等系统级元素,直接重写容易出现绘制偏移、闪烁等问题。正确的做法是自定义JPanel子类,重写其paintComponent()方法实现自定义绘制,再将面板添加到JFrame中。
  3. 不合理的静态变量设计
    你将Model设置为静态变量,会导致状态全局耦合,后续扩展功能时容易出现不可预期的BUG,建议改为普通成员变量由外部注入。

修复方案

1. 修正View类逻辑

public class View extends JFrame{
    // 删掉多余的内部JFrame变量
    private JPanel drawPanel;
    // 去掉static修饰,改为普通成员变量
    private Model model;

    public View(){
        // 不要在这里创建Model,由Controller注入
    }

    public void createFrame(){
        // 直接操作当前View实例(本身就是JFrame)
        this.setSize(500,700);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("Breakout Ball");
        // 新增自定义绘制面板
        drawPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                System.out.println("Hello");
                // 非空判断避免空指针
                if (model == null || model.getPaddle() == null) {
                    return;
                }
                Paddle paddle = model.getPaddle();
                Rectangle paddleImage = new Rectangle(paddle.getX(),paddle.getY(), paddle.getWidth(),paddle.getHeight());
                g2.draw(paddleImage);
            }
        };
        drawPanel.setBackground(Color.BLACK);
        this.add(drawPanel);
        this.setVisible(true);
    }


    public void updateView(Model modelArg){
        this.model = modelArg;
        System.out.println("Hi there");
        System.out.println(SwingUtilities.isEventDispatchThread());
        // 调用绘制面板的repaint触发刷新
        drawPanel.repaint();
    }
    // 删除原来重写的paint方法、静态draw方法
}

2. 优化Controller游戏循环

你原来构造方法中的while循环只会触发两次刷新,不符合游戏的持续刷新需求,建议使用Swing Timer实现稳定的游戏循环,不会阻塞Swing事件调度线程:

public Controller(Model model, View view){
    this.model = model;
    this.view = view;
    initView();
    // 替换原来的while循环,16ms刷新一次约等于60帧
    new Timer(16, e -> doCycle()).start();
}

内容的提问来源于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.02 03:09:04