2012-05-31 58 views
9

動畫(循環)GIF可以以JLabel或HTML(格式化文本組件,如JEditorPane)顯示,並可看作循環。在Swing中顯示動畫BG

但是要加載圖像作爲容器的背景進行繪製,我通常會使用ImageIO.read()Toolkit.getImage()(後者當我懷念上一個千年時)。加載圖像的方法都不會產生循環圖像,通常只是第一幀。

如何加載一個動畫圖像的背景?

回答

10

使用ImageIcon可能是做的最簡單的事情。幾件事情要記住:

  • ImageIcon(URL)本身利用了Toolkit.getImage(URL)。您可能更喜歡使用Toolkit.createImage(URL)而不是 - getImage()可能會使用緩存或共享的圖像數據。

  • ImageIcon利用MediaTracker有效等待圖像完全加載。

所以,您的問題可能沒有使用ToolkitImageIO是一個不同的野獸),而是事實,你不能渲染滿載圖像。嘗試一個有趣的事情是:

Image image = f.getToolkit().createImage(url); 
//... 
ImagePanel imagePanel = new ImagePanel(image); 
imagePanel.prepareImage(image, imagePanel); 
//... 

我的揮杆/ AWT/J2D可能有點模糊,但這個想法是,既然你ImagePanelImageObserver,它可以異步關於圖像信息通知。如果需要,Component.imageUpdate()方法應調用repaint

編輯:

正如在評論中指出,不需要prepareImage電話 - 一個工作示例如下所示。關鍵是重寫的paintComponent方法調用Graphics.drawImage,它提供了ImageObserver鉤子。 imageUpdate方法(在java.awt.Component中執行)將連續調用ImageObserver.FRAMEBITS標誌集。

import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.image.ImageObserver; 
import java.net.MalformedURLException; 
import java.net.URL; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 

public class ImagePanel extends JPanel { 

    private final Image image; 

    public ImagePanel(Image image) { 
     super(); 
     this.image = image; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); 
    } 

    public static void main(String[] args) throws MalformedURLException { 
     final URL url = new URL("http://pscode.org/media/starzoom-thumb.gif"); 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame f = new JFrame("Image"); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setLocationByPlatform(true); 

       Image image = f.getToolkit().createImage(url); 
       ImagePanel imagePanel = new ImagePanel(image); 
       imagePanel.setLayout(new GridLayout(5, 10, 10, 10)); 
       imagePanel.setBorder(new EmptyBorder(20, 20, 20, 20)); 
       for (int ii = 1; ii < 51; ii++) { 
        imagePanel.add(new JButton("" + ii)); 
       } 

       f.setContentPane(imagePanel); 
       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

很棒。測試過'Toolkit.createImage(URL)'作爲'new ImageIcon(url).getImage()'的直接「插入式」替代品,圖片也被循環使用。請注意,我並不打算調用'prepareImage'。 –

+0

明天我會編輯我的回覆,但我也注意到我創建的測試(您的代碼的修改版本)不需要prepareImage調用。我相信對Graphics.drawImage的調用提供了ImageObserver鉤子... – kschneid

+0

只注意到剛纔的編輯。我認爲這可能是我的第一個規範問答,但事實證明你的答案更好!我不確定是否被激怒或被高估找到更多細節。 (再多考慮一下..)好吧,我很高興。感謝您的回答。 :) –

14

要獲得用於自定義繪畫的自行車(動畫)GIF,一個技巧是使用ImageIcon加載它。雖然從問題中列出的兩種方法之一返回的圖像是靜態的,但從ImageIcon獲得的圖像是動畫的。

下面的代碼將添加50個按鈕,然後不久將'縮放星'動畫GIF 的幀作爲BG給它們。 ImagePanel會將圖像拉伸至面板的大小。

  1. 它基於這個圖像。

Zooming Stars GIF

import java.awt.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import java.net.URL; 

class ImagePanel extends JPanel { 

    private Image image; 

    ImagePanel(Image image) { 
     this.image = image; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(image,0,0,getWidth(),getHeight(),this); 
    } 

    public static void main(String[] args) throws Exception { 
     URL url = new URL("http://i.stack.imgur.com/iQFxo.gif"); 
     final Image image = new ImageIcon(url).getImage(); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame f = new JFrame("Image"); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setLocationByPlatform(true); 

       ImagePanel imagePanel = new ImagePanel(image); 
       imagePanel.setLayout(new GridLayout(5,10,10,10)); 
       imagePanel.setBorder(new EmptyBorder(20,20,20,20)); 
       for (int ii=1; ii<51; ii++) { 
        imagePanel.add(new JButton("" + ii)); 
       } 

       f.setContentPane(imagePanel); 
       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

張貼[SSCCE](http://sscce.org/) – mKorbel

+0

感謝這個整潔的SSCCE,我不知道ImageIcon能夠顯示.gif的動畫。我在辯論是否應該爲我的GUI添加一個動畫圖片,現在我知道如果我想添加它,它會相當簡單。 – WilliamShatner

1

我設法讓gif動畫我的JPanel裏面是這樣的:

private JPanel loadingPanel() { 
    JPanel panel = new JPanel(); 
    BoxLayout layoutMgr = new BoxLayout(panel, BoxLayout.PAGE_AXIS); 
    panel.setLayout(layoutMgr); 

    ClassLoader cldr = this.getClass().getClassLoader(); 
    java.net.URL imageURL = cldr.getResource("img/spinner.gif"); 
    ImageIcon imageIcon = new ImageIcon(imageURL); 
    JLabel iconLabel = new JLabel(); 
    iconLabel.setIcon(imageIcon); 
    imageIcon.setImageObserver(iconLabel); 

    JLabel label = new JLabel("Loading..."); 
    panel.add(iconLabel); 
    panel.add(label); 
    return panel; 
} 

這種方法的幾點:
1.圖像文件是罐子內;
2. ImageIO.read()返回一個BufferedImage,它不更新ImageObserver;
3.查找捆綁在jar文件中的圖像的另一種方法是要求Java類加載器(加載程序的代碼)獲取文件。它知道事情在哪裏。

因此,通過這樣做,我能夠在我的JPanel中獲得我的動畫gif,並且它像一個魅力一樣工作。