10

アニメーション化された(循環)GIFは、JLabelまたはHTML(のようなフォーマットされたテキストコンポーネントJEditorPane)で表示され、循環しているように見えます。

しかし、コンテナの背景としてペイントする画像をロードするには、通常、またはのいずれかを使用しますImageIO.read()Toolkit.getImage()最後の千年紀に懐かしいと感じている場合は後者を使用します)。画像をロードするどちらの方法でも、循環画像は生成されません。通常、これは最初のフレームにすぎません。

背景のアニメーション画像を読み込む方法は?

例えば

4

3 に答える 3

16

カスタムペイント用のサイクリング(アニメーション)GIFを取得するには、を使用してロードするのが1つのトリックですImageIcon。質問にリストされている2つの方法のいずれかから返された画像は静的ですが、から取得された画像ImageIconはアニメーション化されています。

以下のコードは50個のボタンを追加し、「ズームスター」のアニメーションGIF1のフレームの直後にBGとしてそれらに追加します。はImagePanel、画像をパネルのサイズに拡大します。

  1. この画像に基づいています。

ズームスター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);
            }
        });
    }
}
于 2012-05-31T15:40:15.553 に答える
13

を使用するImageIconことは、おそらく最も簡単なことです。次の点に注意してください。

  • ImageIcon(URL)それ自体が を利用しToolkit.getImage(URL)ます。Toolkit.createImage(URL)代わりに使用することをお勧めします -getImage()キャッシュまたは共有された画像データを使用できます。

  • ImageIconMediaTrackerイメージが完全にロードされるまで効果的に待機するために a を使用します。

したがって、問題はToolkit( ImageIOis a different beast) の使用ではなく、完全にロードされた画像をレンダリングしていないという事実かもしれません。試してみる興味深いことの1つは次のとおりです。

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

私の Swing/AWT/J2D は少しあいまいかもしれませんが、アイデアはあなたImagePanelが であるためImageObserver、画像情報について非同期に通知できるということです。Component.imageUpdate()メソッドは、必要に応じて呼び出す必要repaintがあります。

編集:

コメントに記載されているように、への呼び出しprepareImageは必要ありません。実際の例を以下に示します。重要なのは、オーバーライドされたメソッドがフックを提供する をpaintComponent呼び出すことです。メソッド ( で実装)は、フラグが設定された状態で継続的に呼び出されます。Graphics.drawImageImageObserverimageUpdatejava.awt.ComponentImageObserver.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://i.stack.imgur.com/iQFxo.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);
            }
        });
    }
}
于 2012-05-31T18:57:08.667 に答える
1

この方法で、JPanel 内にアニメーション gif を取得することができました。

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. イメージ ファイルは jar 内にあります。
2. ImageIO.read() は、ImageObserver を更新しない BufferedImage を返します。
3. jar ファイルにバンドルされているイメージを見つけるもう 1 つの方法は、Java クラス ローダー (プログラムをロードしたコード) にファイルを取得するように要求することです。物がどこにあるかを知っています。

これを行うことで、JPanel 内でアニメーション GIF を取得することができ、魅力的に機能しました。

于 2013-03-01T20:38:37.223 に答える