为啥我在 paintComponent 中的 gif 动画不起作用?

Posted

技术标签:

【中文标题】为啥我在 paintComponent 中的 gif 动画不起作用?【英文标题】:Why is my gif animation in paintComponent not working?为什么我在 paintComponent 中的 gif 动画不起作用? 【发布时间】:2021-07-15 04:14:49 【问题描述】:

我正在创建一个 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");

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

这是我的整个 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。

如果我应该添加任何其他内容,请告诉我,并提前感谢您!

【问题讨论】:

不在您的环境中进行编码,但如果复制的作品听起来像是只需要重新启动动画,可能与此 Animated gif only loops once in Chrome and Firefox 相关...如果没有扩展,请尝试使用带有扩展名的 GIF复制。 【参考方案1】:

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

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

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

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

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

【讨论】:

【参考方案2】:

没关系,我必须复制“explosion.gif”。它现在工作正常! 但是,请让我知道是否有另一种方法可以更快、更有效地执行此操作。谢谢!

【讨论】:

以上是关于为啥我在 paintComponent 中的 gif 动画不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

paintComponent() 被调用了 200 次

paintComponent() 方法中的抗锯齿

super.paintComponent(g) 有啥作用?

使用 JPanel 的 addMouseListener() 和 paintComponent()

java中的paintComponent啥时候被调用

如何根据我的paintComponent中的if条件在我的Java GUI中绘制文本?