paint() 无法绘制 gif 但 png 可以正常工作?

paint() can't draw gif but png works fine?

我正在使用 JLabel 尝试在其上绘制动画 gif 图像。我可以使用构造函数 new JLabel(new ImageIcon(FML.class.getResource("giphy.gif")));,它会工作得很好,但是当我重写 paint 方法时,它似乎根本不想绘制它。图像不是静止的,它不在那里!我应该提一下,下面显示的两种方法都非常适合 PNG 而不是 GIF。我是不是遗漏了什么或者这是一个 java 错误? (使用 java 1.8)

编辑:我环顾四周,似乎我并没有完全偏离我需要做的事情,但我遗漏了一些东西。我看过很多帖子 Like this one 但在这种情况下似乎不起作用。

我应该注意到 class 中实际上没有任何其他内容,它只是一个简单的 JPanel。

    import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FML {

    public static void main(String[] args) {
        new FML();
    }

    public FML() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().setLayout(new FlowLayout());
                frame.getContentPane().add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ImageIcon animatedGif;

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton btn = new JButton(new ImageIcon(FML.class.getResource("FmDxW.png")));
            btn.setSize(50, 50);
            btn.setRolloverEnabled(true);
            animatedGif = new ImageIcon(FML.class.getResource("giphy.gif"));
            btn.setRolloverIcon(animatedGif);
            add(btn);

            btn.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseEntered(MouseEvent e) {
                    animatedGif.getImage().flush();
                }

            });

            //I need this
            final ImageIcon image = new ImageIcon(FML.class.getResource("giphy.gif"));

            //To render over this
            final ImageIcon image2 = new ImageIcon(FML.class.getResource("fmDxW.png"));


            //I'm not understanding why I can add the gif into the constructor but the paint method fails.
            JLabel label = new JLabel(image) {
                @Override
                public void paint(Graphics g) {
                    super.paint(g);
                    g.drawImage(image2.getImage(), 64, 64, this);
                }
            };
            //setSize because I want to be 100% sure that it's loading the correct size.
            //Removing it doesn't affect the problem at hand.
            label.setSize(64, 64);
            add(label);
        }
    }
}
g.drawImage(image2.getImage(), 64, 64, this);

假设您的图片大小为 64,为什么要在标签边界之外绘制第二张图片?当我将位置更改为 (0, 0) 时,gif 对我来说很好(但我没有使用动画 gif)。

both methods shown below work perfectly fine with a PNG but not a GIF.

我不明白我上面给出的原因。无论如何,你用普通的gif试过吗?

这就是为什么您不应该尝试自己管理这幅画的原因,因为现在您需要担心位置,而对位置进行硬编码并不是一个好的做法。让您的布局管理器为您做这件事。

再问一次,你为什么要这样做。为什么要尝试重写 paint 方法来绘制第二张图像?

相反,您应该这样做:

  1. 在 paintComponent() 方法中绘制两个图像
  2. 使用带有 OverlayLayout 的面板,然后您可以将两个标签堆叠在一起。
  3. 您甚至可以将布局的布局管理器设置为 GridBagLayout 之类的东西,然后当您将 JLabel 添加到标签时,它会自动居中。

//setSize because I want to be 100% sure that it's loading the correct size.

您说您知道布局管理器的工作原理。好吧,如果你这样做了,那么你就知道这个语句不会做任何事情,因为布局管理器会覆盖你设置的任何值,所以使用这样的代码是错误的,并且显示出基本缺乏理解,不应该包含在 MCVE 中,因为MCVE`的重点是尽可能简化问题。