【问题标题】:Show an animated BG in Swing在 Swing 中显示动画 BG
【发布时间】:2012-06-05 21:37:31
【问题描述】:

动画(循环)GIF 可以显示在 JLabel 或 HTML 中(在格式化的文本组件中,如 JEditorPane)并被视为循环。

但要加载图像以绘制为容器的背景,我通常会使用ImageIO.read()Toolkit.getImage()(当我怀念上个千年时使用后者)。这两种加载图像的方法都不会导致循环图像,它通常只是第一帧。

如何为背景加载动画图像?

例如

【问题讨论】:

    标签: java image swing background animated-gif


    【解决方案1】:

    要获得用于自定义绘画的循环(动画)GIF,一个技巧是使用 ImageIcon 加载它。虽然从问题中列出的两种方法中的任何一种返回的图像都是静态的,但从 ImageIcon 获得的图像是动画的。

    下面的代码将添加 50 个按钮,然后将“缩放星星”动画 GIF1 的帧作为背景添加到它们。 ImagePanel 会将图像拉伸到面板的大小。

    1. 它基于此图像。

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

    【讨论】:

    • 感谢这个简洁的 SSCCE,我不知道 ImageIcon 能够显示 .gif 的动画。我在争论是否应该在我的 GUI 中添加动画图片,现在我知道如果我想添加它会相当简单。
    【解决方案2】:

    使用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);
    //...
    

    我的 Swing/AWT/J2D 可能有点模糊,但想法是,由于您的 ImagePanelImageObserver,因此可以异步通知图像信息。 Component.imageUpdate() 方法应根据需要调用 repaint

    编辑:

    如 cmets 中所述,不需要调用 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://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);
                }
            });
        }
    }
    

    【讨论】:

    • 很棒的收获。测试Toolkit.createImage(URL) 作为new ImageIcon(url).getImage() 的直接“插入”替代品,并且图像也循环了。请注意,我没有费心打电话给prepareImage
    • 明天我会编辑我的回复,但我也注意到我创建的测试(您的代码的修改版本)不需要 prepareImage 调用。我相信对 Graphics.drawImage 的调用提供了 ImageObserver 钩子...
    • 刚才才注意到编辑。我认为这可能是我的第一个规范问答,但事实证明你的答案更好!我不确定是对被打败感到恼火,还是对找到一个有更多细节的人感到高兴。 (再考虑片刻……)好吧,我很高兴。感谢您的回答。 :)
    【解决方案3】:

    我设法通过这种方式在我的 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()返回一个BufferedImage,不更新ImageObserver;
    3. 另一种查找捆绑在 jar 文件中的图像的方法是询问 Java 类加载器(加载程序的代码)来获取文件。它知道东西在哪里。

    因此,通过这样做,我能够在我的 JPanel 中获取我的动画 gif,它就像一个魅力。

    【讨论】:

      猜你喜欢
      • 2014-03-16
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      • 2014-12-18
      • 2012-11-26
      • 1970-01-01
      相关资源
      最近更新 更多