【问题标题】:Painting a group of objects in a JPanel在 JPanel 中绘制一组对象
【发布时间】:2020-04-19 10:32:49
【问题描述】:

我对 Java 和 GUI 世界还很陌生。现在我正在尝试创建一个非常基本的太空射击游戏。为了创建它,我开始创建一个JFrame,后来我在其中放置了一个名为GamePanelJPanel 的个人扩展,我现在正试图在其上显示我的所有组件。直到这里一切都很清楚,问题来了:我有我的GamePanel,在其中显示我的球员,而在按下S 的KeyEvent 上,球员应该射子弹。我将子弹作为一个数组管理,称为Shooter[]Bullet 对象,由我自己创建:

public class Bullet implements ActionListener{

    Timer Time = new Timer(20, this);

    private int BulletY = 430;
    public int PlayerX;
    public Rectangle Bound = new Rectangle();

    public Bullet(int playerx) {
        this.PlayerX = playerx;
        Time.start();
    }

    public void draw(Graphics g){
        g.setColor(Color.RED);
        g.fillRect(PlayerX + 2, BulletY, 3, 10);

        g.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (Time.isRunning()) {
            BulletY = BulletY - 5;
            Bound = new Rectangle (PlayerX + 2, BulletY, 3, 10);
        }
    }

}

我认为在GamePanelpaint() 方法中调用draw 方法可以让我同时显示所有射出的子弹和玩家。实际发生的情况是,一开始看起来还不错,但是当我按下 S 时,玩家消失了,只射出一颗子弹。你能解释一下为什么吗?这就是我的paint() 方法的样子:

public void paint(Graphics 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);

        //System.out.println("Here I should have painted the player...");

        g.dispose();
    }

BulletsCounter 是我创建的一个计数器,以避免在绘制整个数组时出现任何NullPointerExceptions,当按下 S 时它会增加,因此数组的另一个子弹被初始化和射击。 感谢您的耐心等待,我是该网站的新手,如有任何错误请警告我。

【问题讨论】:

  • 不要调用 g.dispose() + 遵循 java 驼峰命名约定:类大写,属性小写。不遵循命名约定会使您的代码难以阅读。
  • @Chocksmith:实际上, 可以在编码人员获得的 Graphics 对象上调用Graphics#dispose(),例如Graphics g = myBufferedImage.getGraphics();,事实上,你应该在使用完此类资源后将其处理掉以节省资源,但您不应在 JVM 提供给您的 Graphics 对象上调用 .dispose(),这种区别很重要,它这就是我在回答中提到这一点的原因。
  • 将允许我同时显示所有射击的子弹和玩家。 - 是的,如果您的数组包含多个子弹对象,它应该可以工作。您需要发布 minimal reproducible example 来证明问题。
  • 把paint()改成paintComponent()+去掉g.dispose()解决了这个问题,而且你教会了我很多,非常感谢,你太棒了!跨度>

标签: java swing draw paint


【解决方案1】:

您有几个重大问题,首先给出最大的问题:

  • 您正在处理 JVM 提供给您的 Graphics 对象。永远不要这样做,因为这会破坏绘画链。相反,只处置您自己创建的 Graphics 对象。
  • 您在绘图中绘图,这有几个原因,但对动画尤其不利,因为您没有图像的自动双缓冲
  • 您没有在覆盖中调用超级绘画方法,因此不允许 JPanel 进行内务绘画。

建议:

  • 不要丢弃 Graphics 对象,除非您自己创建它,例如从 BufferedImage 中提取一个对象。
  • 重写 JPanel 的paintComponent 方法,而不是它的paint 方法,以便为您提供双缓冲和更平滑的动画。
  • 并首先在您的覆盖中调用 super.paintComponent(g) 以允许进行内务处理

【讨论】:

    猜你喜欢
    • 2021-09-11
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多