为什么我在 paintComponent 中的 gif 动画不工作?

Why is my gif animation in paintComponent not working?

我正在创建一个 Java 游戏,在这个游戏中,我有一个可以由用户四处移动的飞机,但是如果飞机撞到任何一侧,它应该爆炸 - 这意味着应该在那个位置发生爆炸。我使用了诸如 Why gif animation doesn't animate when using it in paintComponent()? 和其他链接来了解如何制作 gif 动画,但是,我的代码不起作用。

相关代码如下:

            ImageIcon ii = new ImageIcon(this.getClass().getResource("explosion.gif"));
            Graphics2D g2d = (Graphics2D)g;
            
            g2d.drawImage(ii.getImage(), planeX, planeY, this);
            System.out.println("drawn");

尽管控制台上正在打印“drawn”,但不会加载爆炸 gif。我检查了文件名,它是正确的。但是,我确实在我的代码中的其他地方使用了相同的 gif 并且它在那里工作,所以有什么东西可以防止 gif 在 Java?

中被使用两次

这是我的整个 paintComponent() 方法:

        super.paintComponent(g);
        
        setFocusable(true);
        requestFocus();
        
        background = new ImageIcon("bg.png").getImage();
        g.drawImage(background, -6, 0, 700, 700, null); //background of JPanel
        
        if (!hit) g.drawImage(plane, planeX, planeY, planeLen, planeHei, null);  //only draw plane if not exploded
        else if (count == 0) 
        {
            ImageIcon ii = new ImageIcon(this.getClass().getResource("explosion.gif"));
            Graphics2D g2d = (Graphics2D)g;
            
            g2d.drawImage(ii.getImage(), planeX, planeY, this); //doesn't work
            System.out.println("drawn"); //printed
        }

        title = new ImageIcon("title.png").getImage(); //transparent, is drawn
        g.drawImage(title, -9, 20, 700, 218, null);
        
        title2 = new ImageIcon("title2.png").getImage(); //transparent, is drawn
        g.drawImage(title2, 10, 245, 670, 20, null);

我检查了title和title2,是透明的,意思是爆炸应该可以看到。我什至在那两张图片下方尝试过,但仍然看不到爆炸。我也在这个面板上使用 JButtons 和 KeyListeners。

如果我还需要补充什么,请告诉我,在此先感谢您!

没关系,我不得不复制“explosion.gif”。现在工作正常! 但是,如果有另一种更快更有效的方法,请告诉我。谢谢!

您应该始终将 this 作为绘画方法中 drawImage 的最终参数传递。如果图像有多个帧,或者图像在后台加载,这会告诉组件在更多图像可用时再次绘制自身。

组件的绘制经常发生。它由系统控制,而不仅仅是通过调用组件的 repaint 方法的代码。事实上,绘画每秒发生多次是很常见的。许多超出程序员控制的系统事件都可以触发绘制,例如用户移动 window,或另一个 window 移动,甚至用户移动鼠标。

因此,绘画不应执行加载文件等缓慢操作。将图像加载从绘画方法中移出,并移至 class 的构造函数中。将 Image 对象存储在私有字段中,paintComponent 可以在其中一次又一次地使用它们,而无需为每幅画重新加载它们 运行.

由于绘制的时间不受您的控制,因此切勿在绘制方法中更改组件的状态,这一点很重要。将 setFocusablerequestFocus 移出您的 paintComponent 方法。这些调用应该在构建组件并将其添加到 window.

的代码中

最后,请注意,如果您将应用程序打包在 .jar 文件中,则无法从文件加载图像。 .jar 文件是单个压缩档案;其中的条目不再是文件,它们只是存档中的字节序列。使用 getResource 加载所有文件将解决此问题,因为 getResource 会查看 class 路径中的每个 .jar 文件。