Java GIF动画未正确重新绘制
我正在尝试设置GIF图像的动画。动画效果不错,但画得不好 它显示如下(非动画屏幕截图): 在图中,尾巴摆动如下: 正如您所看到的,图像没有很好地重新绘制。我不想使用JLabels,但它不能正常工作,所以我遵循了 我的代码如下:Java GIF动画未正确重新绘制,java,swing,animation,gif,imageicon,Java,Swing,Animation,Gif,Imageicon,我正在尝试设置GIF图像的动画。动画效果不错,但画得不好 它显示如下(非动画屏幕截图): 在图中,尾巴摆动如下: 正如您所看到的,图像没有很好地重新绘制。我不想使用JLabels,但它不能正常工作,所以我遵循了 我的代码如下: public void draw(JPanel canvas, Graphics2D g2d, int x, int y) { getFrontImage().paintIcon(canvas, g2d, x, y); } ImageIcon gif = new
public void draw(JPanel canvas, Graphics2D g2d, int x, int y) {
getFrontImage().paintIcon(canvas, g2d, x, y);
}
ImageIcon gif = new ImageIcon(getClass().getResource(filename));
在其中检索并保存图像,如下所示:
public void draw(JPanel canvas, Graphics2D g2d, int x, int y) {
getFrontImage().paintIcon(canvas, g2d, x, y);
}
ImageIcon gif = new ImageIcon(getClass().getResource(filename));
在JPanel画布中,我制作了一个绘制方法和一个计时器线程,每10毫秒重新绘制一次。这适用于除GIF之外的所有内容。有人能帮我吗
---编辑
很抱歉误解了,我已经将图像更新为我实际使用的图像。我希望得到正确的答案不会太麻烦…好的,所以经过大量的研究,我终于能够将框架的处理方法更改为
restoreToBackgroundColor
。基本上,这意味着动画不是一个增量更改,而是一个完整的帧替换
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AnimatedGifTest1 {
public static void main(String[] args) {
new AnimatedGifTest1();
}
public AnimatedGifTest1() {
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.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private ImageIcon image;
public PaintPane() {
image = new ImageIcon(getClass().getResource("/ertcM02.gif"));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getIconWidth(), image.getIconHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // This is very important!
int x = (getWidth() - image.getIconWidth()) / 2;
int y = (getHeight() - image.getIconHeight()) / 2;
image.paintIcon(this, g, x, y);
}
}
}
已更新…
因此,我终于能够查看您正在使用的gif的处理方法,该方法设置为restoreToPrevious
,根据方法:
恢复到以前的状态。解码器需要将图形覆盖的区域恢复为渲染图形之前的区域
其中,我上面提供的图像使用了restoreToBackgroundColor
,根据以下方法:
恢复到背景色。图形使用的区域必须恢复为背景色
您可以使用以下代码自己检查它
public static class AnimatedGif {
public enum DisposalMethod {
RESTORE_TO_BACKGROUND,
RESTORE_TO_PREVIOUS,
DO_NOT_DISPOSE,
UNSPECIFIED;
public static DisposalMethod find(String text) {
DisposalMethod dm = UNSPECIFIED;
System.out.println(text);
switch (text) {
case "restoreToBackgroundColor":
dm = RESTORE_TO_BACKGROUND;
break;
case "restoreToPrevious":
dm = RESTORE_TO_PREVIOUS;
break;
}
return dm;
}
}
private List<ImageFrame> frames;
private int frame;
public AnimatedGif(JComponent player, URL url) throws IOException {
frames = new ArrayList<>(25);
try (InputStream is = url.openStream(); ImageInputStream stream = ImageIO.createImageInputStream(is)) {
Iterator readers = ImageIO.getImageReaders(stream);
if (!readers.hasNext()) {
throw new RuntimeException("no image reader found");
}
ImageReader reader = (ImageReader) readers.next();
reader.setInput(stream); // don't omit this line!
int n = reader.getNumImages(true); // don't use false!
System.out.println("numImages = " + n);
for (int i = 0; i < n; i++) {
BufferedImage image = reader.read(i);
ImageFrame imageFrame = new ImageFrame(image);
IIOMetadata imd = reader.getImageMetadata(i);
Node tree = imd.getAsTree("javax_imageio_gif_image_1.0");
NodeList children = tree.getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
Node nodeItem = children.item(j);
NamedNodeMap attr = nodeItem.getAttributes();
switch (nodeItem.getNodeName()) {
case "ImageDescriptor":
ImageDescriptor id = new ImageDescriptor(
getIntValue(attr.getNamedItem("imageLeftPosition")),
getIntValue(attr.getNamedItem("imageTopPosition")),
getIntValue(attr.getNamedItem("imageWidth")),
getIntValue(attr.getNamedItem("imageHeight")),
getBooleanValue(attr.getNamedItem("interlaceFlag")));
imageFrame.setImageDescriptor(id);
break;
case "GraphicControlExtension":
GraphicControlExtension gc = new GraphicControlExtension(
DisposalMethod.find(getNodeValue(attr.getNamedItem("disposalMethod"))),
getBooleanValue(attr.getNamedItem("userInputFlag")),
getBooleanValue(attr.getNamedItem("transparentColorFlag")),
getIntValue(attr.getNamedItem("delayTime")) * 10,
getIntValue(attr.getNamedItem("transparentColorIndex")));
imageFrame.setGraphicControlExtension(gc);
break;
}
}
frames.add(imageFrame);
}
} finally {
}
}
protected String getNodeValue(Node node) {
return node == null ? null : node.getNodeValue();
}
protected int getIntValue(Node node) {
return node == null ? 0 : getIntValue(node.getNodeValue());
}
protected boolean getBooleanValue(Node node) {
return node == null ? false : getBooleanValue(node.getNodeValue());
}
protected int getIntValue(String value) {
return value == null ? 0 : Integer.parseInt(value);
}
protected boolean getBooleanValue(String value) {
return value == null ? false : Boolean.parseBoolean(value);
}
public class ImageFrame {
private BufferedImage image;
private ImageDescriptor imageDescriptor;
private GraphicControlExtension graphicControlExtension;
public ImageFrame(BufferedImage image) {
this.image = image;
}
protected void setImageDescriptor(ImageDescriptor imageDescriptor) {
this.imageDescriptor = imageDescriptor;
}
protected void setGraphicControlExtension(GraphicControlExtension graphicControlExtension) {
this.graphicControlExtension = graphicControlExtension;
System.out.println(graphicControlExtension.getDisposalMethod());
}
public GraphicControlExtension getGraphicControlExtension() {
return graphicControlExtension;
}
public BufferedImage getImage() {
return image;
}
public ImageDescriptor getImageDescriptor() {
return imageDescriptor;
}
}
public class GraphicControlExtension {
private DisposalMethod disposalMethod;
private boolean userInputFlag;
private boolean transparentColorFlag;
private int delayTime;
private int transparentColorIndex;
public GraphicControlExtension(DisposalMethod disposalMethod, boolean userInputFlag, boolean transparentColorFlag, int delayTime, int transparentColorIndex) {
this.disposalMethod = disposalMethod;
this.userInputFlag = userInputFlag;
this.transparentColorFlag = transparentColorFlag;
this.delayTime = delayTime;
this.transparentColorIndex = transparentColorIndex;
}
public int getDelayTime() {
return delayTime;
}
public DisposalMethod getDisposalMethod() {
return disposalMethod;
}
public int getTransparentColorIndex() {
return transparentColorIndex;
}
public boolean isTransparentColorFlag() {
return transparentColorFlag;
}
public boolean isUserInputFlag() {
return userInputFlag;
}
}
public class ImageDescriptor {
private int imageLeftPosition;
private int imageTopPosition;
private int imageHeight;
private int imageWeight;
private boolean interlaced;
public ImageDescriptor(int imageLeftPosition, int imageTopPosition, int imageHeight, int imageWeight, boolean interlaced) {
this.imageLeftPosition = imageLeftPosition;
this.imageTopPosition = imageTopPosition;
this.imageHeight = imageHeight;
this.imageWeight = imageWeight;
this.interlaced = interlaced;
}
public int getImageHeight() {
return imageHeight;
}
public int getImageLeftPosition() {
return imageLeftPosition;
}
public int getImageTopPosition() {
return imageTopPosition;
}
public int getImageWeight() {
return imageWeight;
}
public boolean isInterlaced() {
return interlaced;
}
}
}
公共静态类{
公共枚举处置方法{
将_还原到_后台,
将_还原为_上一个,
不要处理,
未指明;
公共静态DisposalMethod查找(字符串文本){
处置方法dm=未指定;
System.out.println(文本);
开关(文本){
案例“restoreToBackgroundColor”:
dm=将_恢复到_背景;
打破
“恢复原状”一案:
dm=将_恢复到_之前;
打破
}
返回dm;
}
}
私有列表框架;
私有int帧;
公共AnimatedGif(jComponentPlayer,URL)引发IOException{
帧=新阵列列表(25);
try(InputStream is=url.openStream();ImageInputStream=ImageIO.createImageInputStream(is)){
迭代器读卡器=ImageIO.getImageReaders(流);
如果(!readers.hasNext()){
抛出新的RuntimeException(“未找到图像读取器”);
}
ImageReader=(ImageReader)readers.next();
reader.setInput(stream);//不要忽略这一行!
int n=reader.getNumImages(true);//不要使用false!
System.out.println(“numImages=“+n”);
对于(int i=0;i