Multiple instances of the same animated GIF in a Canvas (Java)

坚强是说给别人听的谎言 提交于 2019-12-23 18:20:13

问题


So I'm making a game where you can put bombs on the location of your character. Each bomb is associated with a GIF image when the bomb is displayed and eventually go BOOM (think about Bomberman).

The problem was, when i tried to paint more than one bomb on the screen, it was painted from the last frame of the GIF. Investigating, I found the method image.flush() to reset the GIF cicle but now the problem is that every time I paint a second bomb on the screen, the GIF cycle is reset for all previously bombs on screen.

Here is my constructor for each bomb:

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();
}

Every bomb i create enters an ArrayList (listTnt) and is removed after 6 secs, so i only paint the bombs already active.

Here is my method for drawing:

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

EDIT: Seems that the problem was ImageIcon, since it reuses the image using Toolkit.getImage. Instead, Toolkit.createImage create a not reusable image.

Here is my new constructor for Tnt that worked perfectly:

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");
}

I dont even need image.flush() now. Thank you all.


回答1:


The underlying Image is being reused amongst each ImageIcon. Judging by the OpenJDK source code, it appears to be due to the fact that each simply requests the Image via Toolkit.getImage. This method has a nifty caveat, however, which explains the issue at hand:

The underlying toolkit attempts to resolve multiple requests with the same filename to the same returned Image.

Instead, you should skip the ImageIcon step completely (since it's inappropriate to be using a Swing class unnecessarily in the first place), and instead call Toolkit.createImage, which states in the documentation:

The returned Image is a new object which will not be shared with any other caller of this method or its getImage variant.

Good luck.




回答2:


As I did not know how to solve this, I tried @super_ solution and it works quite nicely. I share the code for anyone who wants an example. +1 to him

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();
            }
        });
    }

}


来源:https://stackoverflow.com/questions/11745804/multiple-instances-of-the-same-animated-gif-in-a-canvas-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!