【问题标题】:Multiple instances of the same animated GIF in a Canvas (Java)Canvas (Java) 中相同动画 GIF 的多个实例
【发布时间】:2012-07-29 13:20:08
【问题描述】:

所以我正在制作一个游戏,你可以在角色所在的位置放置炸弹。当炸弹显示并最终爆炸时,每个炸弹都与一个 GIF 图像相关联(想想炸弹人)。

问题是,当我尝试在屏幕上绘制多个炸弹时,它是从 GIF 的最后一帧开始绘制的。经过调查,我找到了重置 GIF cicle 的方法 image.flush() 但现在的问题是,每次我在屏幕上绘制第二个炸弹时,屏幕上所有以前的炸弹都会重置 GIF 周期。

这是每个炸弹的构造函数:

public Tnt(int x, int y){
    this.x = x;
    this.y = y;
    ImageIcon ii = new ImageIcon("src/main/resources/modelObjects/tnt.gif");
    image = ii.getImage();
    image.flush();
}

我创建的每个炸弹都进入一个 ArrayList (listTnt) 并在 6 秒后被移除,所以我只绘制已经激活的炸弹。

这是我的绘图方法:

public void draw(Graphics2D g2d, JPanel board){
    for(Tnt tnt: listTnt){          
        g2d.drawImage(tnt.getImage(), tnt.getX(), tnt.getY(), board);
    }
}

编辑:似乎问题出在 ImageIcon 上,因为它使用 Toolkit.getImage 重用了图像。相反, Toolkit.createImage 创建一个不可重用的图像。

这是我的 Tnt 新构造函数,效果很好:

public Tnt(int x, int y){
    this.x = x;
    this.y = y;
    Toolkit t = Toolkit.getDefaultToolkit ();
    image = t.createImage("src/main/resources/modelObjects/tnt.gif");
}

我现在什至不需要image.flush()。谢谢你们。

【问题讨论】:

  • image的范围是什么?
  • 在应用程序的主游戏状态中,我有一个炸弹列表。当我在游戏中投下炸弹时,会创建一个新的 Tnt 并将其添加到列表中,并在 6 秒(炸弹生命周期)后从列表中删除炸弹。 draw 方法只绘制列表中的炸弹,image 是 Tnt 中的一个变量。

标签: java swing gif graphics2d animated-gif


【解决方案1】:

底层Image 在每个ImageIcon 中被重用。 从OpenJDK source code 来看,这似乎是因为每个人都只是通过Toolkit.getImage 请求图像。 然而,这种方法有一个很好的警告,它解释了手头的问题:

底层工具包尝试将具有相同文件名的多个请求解析为相同的返回图像。

相反,您应该完全跳过ImageIcon 步骤(因为首先不必要地使用Swing 类是不合适的),而是调用Toolkit.createImage,文档中指出:

返回的 Image 是一个新对象,不会与此方法或其 getImage 变体的任何其他调用者共享。

祝你好运。

【讨论】:

  • +1 很好的解释和解决方案。我在尝试您以前不知道的解决方案时添加了一个示例代码。
【解决方案2】:

由于我不知道如何解决这个问题,我尝试了@super_ 解决方案,它工作得很好。我为任何想要示例的人分享代码。给他+1

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestAnimatedGif {

    private static final int IMAGE_COUNT = 9;

    protected void initUI() {
        JFrame frame = new JFrame(TestAnimatedGif.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JPanel panel = new JPanel();
        frame.add(panel);
        frame.setSize(600, 400);
        frame.setVisible(true);
        final Timer t = new Timer(1000, null);
        t.addActionListener(new ActionListener() {

            int count = 0;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (count < IMAGE_COUNT) {
                    try {
                        JLabel image = new JLabel(new ImageIcon(Toolkit.getDefaultToolkit().createImage(
                                new URL("http://www.sitevip.net/gifs/bomba/BOMB-B_animado.gif"))));
                        panel.add(image);
                        count++;
                        panel.revalidate();
                        panel.repaint();
                        System.err.println("image added");
                    } catch (MalformedURLException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                } else {
                    t.stop();
                }
            }
        });
        t.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestAnimatedGif().initUI();
            }
        });
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 2013-05-15
    • 2015-10-21
    • 2019-12-15
    • 2013-03-11
    • 1970-01-01
    • 2018-09-16
    • 2012-09-15
    相关资源
    最近更新 更多