2012-07-31 190 views
3

所以我在做一個遊戲,你可以把炸彈在你的角色的位置。當炸彈被顯示時,每個炸彈都與GIF圖像相關聯,並最終進入BOOM(想想炸彈人)。多個實例

的問題是,當我試圖在屏幕上繪製一個以上的炸彈,它是從GIF的最後一幀畫。在調查中,我找到了image.flush()方法來重置GIF Cicle,但現在問題是每當我在屏幕上繪製第二個炸彈時,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()現在。謝謝你們。

+2

'image'的範圍是什麼? – trashgod 2012-07-31 17:36:42

+0

在應用程序的主要遊戲狀態中,我有一個炸彈列表。當我在遊戲中放置炸彈時,會創建一個新的Tnt並添加到列表中,並在6秒(炸彈生命週期)後將炸彈從列表中移除。 'draw'方法只從list和'image'中繪製炸彈是Tnt內的一個變量。 – 2012-07-31 18:00:04

+0

請參閱[在Swing中顯示動畫BG](http://stackoverflow.com/questions/10836832/show-an-animated-bg-in-swing)。 – 2012-07-31 23:07:02

回答

6

底層Image被重用之間每個ImageIcon。 根據OpenJDK source code來判斷,這似乎是因爲每個人都只是通過Toolkit.getImage來請求圖片。 這種方法有一個漂亮的警告,不過,這也說明當前的問題:

底層工具包試圖對具有相同的文件名相同的圖像返回多個請求。

相反,你應該完全跳過ImageIcon步驟(因爲它是不恰當的擺在首位不必要地使用Swing類是),而是調用Toolkit.createImage,在文檔中的規定:

的返回的Image是一個新對象,它不會與此方法或其getImage變體的任何其他調用方共享。

好運。

+1

這聽起來對我來說是正確的。 – aglassman 2012-07-31 17:56:28

+1

很好,謝謝你,先生! – 2012-07-31 18:12:14

+0

+1很好的解釋和解決方案。我添加了一個示例代碼,因爲我嘗試了我以前不知道的解決方案。 – 2012-07-31 20:46:20

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

} 
+0

+1 [sscce](http://sscce.org/)和@super_。 – trashgod 2012-07-31 23:20:50