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

Java JPanel多对象绘制异常:按S键后玩家消失仅显示单颗子弹

问题根源分析与修复方案

嘿,我来帮你揪出这个问题的关键所在!

核心问题:错误调用了g.dispose()

你的问题完全出在Bullet类的draw()方法里的这一行:

g.dispose();

Swing在调用GamePanel.paint()时,会传递一个共享的Graphics上下文对象给你,这个对象是由AWT/Swing的绘制系统管理的。你在绘制单颗子弹后就调用g.dispose(),会直接销毁这个Graphics对象——这就导致:

  1. 循环里后续的子弹根本没法再使用这个失效的Graphics进行绘制,所以你只能看到第一颗子弹;
  2. 绘制玩家的代码在子弹绘制之后执行,此时Graphics已经被释放,玩家自然画不出来。

修复步骤

只需要把Bullet.draw()里的g.dispose()删掉就行!Graphics资源的生命周期不需要你手动管理,Swing会在绘制完成后自动处理这件事。

修改后的Bullet.draw()方法:

public void draw(Graphics g){
    g.setColor(Color.RED);
    g.fillRect(PlayerX + 2, BulletY, 3, 10);
    // 删掉g.dispose()!
}

额外的优化建议

为了让你的代码更规范、更健壮,再给你几个小提示:

  • 优先重写paintComponent()而非paint():JPanel的标准绘制方法是paintComponent(),重写它时记得先调用super.paintComponent(g),这样能确保面板的背景被正确刷新,避免画面残留:
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 必须先调用这个
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, 500, 500);
        for(int i = 0; i < BulletsCounter; i++) {
            Shooter[i].draw(g);
        }
        g.setColor(Color.RED);
        g.fillRect(PlayerX, PlayerY, 20, 20);
        // 这里也不要加g.dispose()
    }
    
  • 用ArrayList<Bullet>代替数组:手动维护BulletsCounter和数组容易出错,用动态列表可以更方便地添加、移除子弹:
    private List<Bullet> bullets = new ArrayList<>();
    // 发射子弹时:
    bullets.add(new Bullet(PlayerX));
    // 绘制时:
    for(Bullet bullet : bullets) {
        bullet.draw(g);
    }
    
  • 遵守Java命名规范:变量名Time应该改成小写开头的timer,类名、方法名的命名也要保持一致,提升代码可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:48:12