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

Java中绘制多个对象仅显示最后一个的问题求助

解决只显示最后一个绘制对象的问题

看起来你遇到的问题很典型——虽然所有对象的repaint()都被调用了,但只有最后一个能显示出来。结合Swing的绘制机制和你的代码结构,我整理了几个最可能的原因和对应的解决方法:

1. Game类的paintComponent没有遍历所有对象绘制

这是最常见的原因。如果你的Game类是负责绘制的容器(比如JPanel),但它的paintComponent方法只绘制了ArrayList里的最后一个元素,那不管调用多少次repaint(),最终只会显示最后一个。

错误示例:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // 只绘制最后一个元素
    if (!drawableList.isEmpty()) {
        DrawableObject lastObj = drawableList.get(drawableList.size() - 1);
        lastObj.draw(g);
    }
}

正确写法:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // 遍历所有元素逐个绘制
    for (DrawableObject obj : drawableList) {
        obj.draw(g);
    }
}

2. 每个对象调用自己的repaint(),而非统一触发Game类的重绘

Swing会合并短时间内的多个repaint()请求,只执行一次重绘。如果每个对象都单独调用自己的repaint(),但这些对象不是被添加到容器中的Swing组件,它们的绘制逻辑根本不会被触发。正确的做法是统一由Game类触发重绘。

错误示例(对象的actionPerformed):

@Override
public void actionPerformed(ActionEvent e) {
    // 更新自身状态
    this.x += 1;
    // 调用自己的repaint(),但如果不是Component,这毫无意义
    this.repaint();
}

正确写法:

让Game类作为统一的重绘入口,对象的actionPerformed只负责更新状态,然后通知Game类重绘:

// GameObject类的actionPerformed
@Override
public void actionPerformed(ActionEvent e) {
    // 仅更新自身状态
    this.x += 1;
    // 通知Game类触发重绘(可以通过传入Game引用或回调实现)
    game.repaint();
}

// Game类的actionPerformed
@Override
public void actionPerformed(ActionEvent e) {
    for (GameObject obj : gameObjects) {
        obj.actionPerformed(e);
    }
    // 或者更简洁的流程:让对象只负责状态更新,Game统一调用重绘
    // for (GameObject obj : gameObjects) {
    //     obj.update();
    // }
    // this.repaint();
}

3. ArrayList中存储的是同一个对象的重复引用

如果你的代码在添加对象到ArrayList时,重复添加了同一个对象的引用(而不是创建新对象),那ArrayList里的所有元素其实都是同一个对象。即使你修改了“每个对象”的状态,最终只是修改了同一个对象的状态,绘制时当然只会显示最后一次修改的结果。

错误示例:

GameObject obj = new GameObject();
for (int i = 0; i < 5; i++) {
    obj.setPosition(i * 50, 100); // 修改同一个对象的位置
    gameObjects.add(obj); // 添加同一个引用
}

正确写法:

每次循环都创建新的对象实例:

for (int i = 0; i < 5; i++) {
    GameObject obj = new GameObject(); // 每次创建新对象
    obj.setPosition(i * 50, 100);
    gameObjects.add(obj);
}

4. 绘制区域重叠或坐标设置错误

如果所有对象都被绘制在同一个坐标位置,后面的对象会覆盖前面的,看起来就像只显示了最后一个。你可以在每个对象的draw方法里打印它们的坐标,确认是否位置重复:

public void draw(Graphics g) {
    System.out.println("绘制对象:x=" + x + ", y=" + y);
    g.fillRect(x, y, width, height);
}

如果坐标确实重复,调整每个对象的初始位置即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:25:31