You need to enable JavaScript to run this app. Java Swing创建类对象时代码崩溃,如何跨类调用repaint移动矩形
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing创建类对象时代码崩溃,如何跨类调用repaint移动矩形

核心问题

代码崩溃的根本原因是循环实例化导致栈溢出:test类实例化test2,test2类实例化test3,test3类中又再次实例化test2,三者形成无限循环创建对象的逻辑,最终内存耗尽程序崩溃。

修复步骤

1. 解除循环依赖

删除test3类中主动实例化test2的代码,改为通过构造方法传入已经创建的test2实例。
修改后的test3构造部分:

public class test3 {
    public boolean down = false;
    public boolean up = false;
    public int playerXpos = 45;
    public int playerYpos = 300;
    public int playerWidth = 15;
    public int playerHeight = 80;
    Rectangle player = new Rectangle(playerXpos, playerYpos, playerWidth, playerHeight);
    // 仅保留test2成员变量,不主动实例化
    test2 theBoard;

    // 新增构造方法接收外部传入的test2实例
    public test3(test2 board){
        this.theBoard = board;
    }
    // 其余方法保留,需要修改keyPressed中的错误逻辑
}

2. 修改test2类的实例化逻辑

创建test3实例时把当前test2对象传入,同时绑定键盘监听器,否则键盘操作不会触发响应:

public class test2 extends JPanel {
    public int playerScore = 0;
    public int opponentScore = 0;
    // 传入当前test2实例this初始化test3
    test3 player = new test3(this);
    
    // 新增构造方法绑定监听器
    public test2(){
        this.addKeyListener(player);
        // JPanel默认不获取焦点,必须设置才能响应键盘事件
        this.setFocusable(true);
    }

    // 重写paintComponent而非paint,是Swing标准绘制方法
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        board(g);
        g.setColor(Color.WHITE);
        // 同步更新矩形坐标,否则绘制不会变化
        player.player.y = player.playerYpos;
        g2d.fill(player.player);
    }

    public void board(Graphics g) {
        g.setColor(Color.black);
        g.fillRect(0, 0, 900, 700);
    }
}

3. 修复键盘事件的错误逻辑

原代码中keyPressed的for循环完全冗余,且向下移动的坐标逻辑写反,修改后代码如下:

public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_UP) {
        playerYpos -= 20;
        if (playerYpos < 50) {
            playerYpos = 50;
        }
        theBoard.repaint();
    }
    if (e.getKeyCode() == KeyEvent.VK_DOWN) {
        playerYpos += 20;
        // 窗口高度仅705,限制最大坐标避免移出可视区域
        if (playerYpos > 600) {
            playerYpos = 600;
        }
        theBoard.repaint();
    }
}

其他优化提示

  • 现有实现按一次按键移动一次,如果需要按住按键连续移动,可结合javax.swing.Timer实现平滑位移
  • 空实现的actionPerformed方法目前无实际作用,可在添加定时器后再补充对应逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 01:24:00