paint() 无法绘制 gif 但 png 可以正常工作?
Posted
技术标签:
【中文标题】paint() 无法绘制 gif 但 png 可以正常工作?【英文标题】:paint() can't draw gif but png works fine? 【发布时间】:2018-02-20 09:18:26 【问题描述】:我正在使用 JLabel 尝试在其上绘制动画 gif 图像。我可以使用构造函数new JLabel(new ImageIcon(FML.class.getResource("giphy.gif")));
,它会工作得很好,但是当我重写paint方法时,它似乎根本不想绘制它。图像不是静止的,它不存在!我应该提一下,下面显示的两种方法都适用于 PNG 但不适用于 GIF。我错过了什么还是这是一个java错误?
(使用 java 1.8)
编辑:我一直在环顾四周,似乎我并没有完全偏离我需要做的事情,但我错过了一些东西。我看过很多帖子Like this one,但在这种情况下似乎不起作用。
我应该注意,课堂上实际上没有其他内容,它是一个简单的 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);
【问题讨论】:
1) 您不应该在绘画方法中进行 I/O。 2) 自定义绘画(需要时)是通过覆盖paintComponent(...) 来完成的。 3)无需自定义绘制,只需在JLabel中添加一个Icon即可。 4) 不要在标签上使用 setSize(...)。这意味着您使用的是空布局。不要使用空布局。 Swing 旨在与布局管理器一起使用。阅读 Swing tutorial 了解 Swing 基础知识。有关于使用图标和自定义绘画的部分。 这只是测试代码,我永远不会在生产代码上使用 IO。话虽如此,在我的具体实现中确实需要自定义绘画。尽管如此,我还是尝试将 IO 移出渲染循环,因为这可能是问题所在,但没有骰子。问题依然存在。 -edit- 再次,这是测试代码,我知道如何使用布局管理器和自定义绘画并不复杂。我觉得我只是错过了一些具体的东西。 如果您知道如何使用布局管理器并进行自定义绘画,那么您应该没有问题,为什么要覆盖paint()?。但显然你确实有问题。我不知道您为什么要扩展 JLabel 以进行自定义绘画,以简单地尝试绘制图像。 JLabel 无需任何自定义即可为您执行此操作。我看到的所有代码都表明您不了解 Swing 的基础知识。发布正确的minimal reproducible example,使用正确的 Swing 技术演示问题。 在那里,我已经包含了整个班级并添加了 cmets 来帮助解释我正在尝试做的事情。 【参考方案1】:g.drawImage(image2.getImage(), 64, 64, this);
假设您的图片大小为 64,您为什么要尝试在标签范围之外绘制第二张图片?当我将位置更改为 (0, 0) 时,gif 对我来说很好(但我没有使用动画 gif)。
下面显示的两种方法都适用于 PNG 但不适用于 GIF。
我不明白我上面给出的原因。不管怎样,你用普通的 gif 试过了吗?
这就是为什么您不应该尝试自己管理绘画的原因,因为现在您需要担心位置并且硬编码位置不是一个好习惯。让您的布局管理器为您执行此操作。
再说一遍,你为什么要这样做。你为什么要覆盖paint方法来绘制第二张图像?
相反,您应该这样做:
-
在 paintComponent() 方法中绘制两个图像
使用带有
OverlayLayout
的面板,然后您可以将两个标签堆叠在一起。
您甚至可以将布局的布局管理器设置为 GridBagLayout 之类的东西,然后当您将 JLabel 添加到标签时,它会自动居中。
//setSize 因为我想 100% 确定它正在加载正确的大小。
您说您知道布局管理器的工作原理。好吧,如果你这样做了,那么你知道这个语句不会做任何事情,因为布局管理器将覆盖你设置的任何值,所以使用这样的代码是错误的,并且显示出基本缺乏理解,并且不应该包含在 MCVE
中MCVE`的目的就是尽可能的简化问题。
【讨论】:
以上是关于paint() 无法绘制 gif 但 png 可以正常工作?的主要内容,如果未能解决你的问题,请参考以下文章
QT 三大绘图类:QPixmap/QImage/QPicture