GIF ImageIcon 在 Java Swing 中不断闪烁

Posted

技术标签:

【中文标题】GIF ImageIcon 在 Java Swing 中不断闪烁【英文标题】:GIF ImageIcon keeps flickering in Java Swing 【发布时间】:2018-11-03 10:47:55 【问题描述】:

我必须在学校用 Java Swing 做一个小游戏。我为它创建了一些 gif,想把它们放进去,我做到了,但问题是 gif 有时会闪烁。我真的在互联网上找不到任何东西,老实说,我什至不知道从哪里开始看。

我的代码:

import javax.swing.*;
import java.awt.*;
import java.net.URL;

public class Chicken extends JFrame 

    private int canvasWidth = 560;
    private int canvasHeight = 480;

    private Color sideGreen = new Color(14, 37, 14);
    private Color gapGreen = new Color(56, 148, 56);
    private Color edgeGreen = new Color(49, 129, 49);

    private Image chicken;
    private Image cookie;

    private DrawCanvas canvas;

    public Chicken() 
        canvas = new DrawCanvas();

        canvas.setPreferredSize(new Dimension(canvasWidth, canvasHeight));

        try 
            addImages();
         catch (Exception ex) 
            ex.printStackTrace();
        

        Container cp = getContentPane();
        cp.add(canvas);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setTitle("Chicken");
        pack();
        setVisible(true);
    

    private class DrawCanvas extends JPanel 

        @Override
        public void update(Graphics g) 
            paintComponent(g);
        

        @Override
        public void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            setDoubleBuffered(true);
            setBackground(Color.BLACK);
            g2.setColor(sideGreen);
            g2.fillRect(0, 0, 80, canvasHeight);
            g2.fillRect(canvasWidth - 80, 0, 80, 480);
            g2.setColor(gapGreen);
            g2.fillRect(80, 0, 400, 100);
            g2.fillRect(80, canvasHeight - 100, 400, 100);
            g2.setColor(edgeGreen);
            g2.fillRect(80, 80, 400, 20);
            g2.fillRect(80, canvasHeight - 100, 400, 20);
            g2.drawImage(cookie, 85, 5, this);
            g2.drawImage(chicken, 150, 120, this);
        
    

    private void addImages() throws Exception 
        ImageIcon iconCookie = new ImageIcon(new URL("https://i.stack.imgur.com/1PcWC.gif"));
        Image cookieimage = iconCookie.getImage();
        Image newimg = cookieimage.getScaledInstance(70, 70, Image.SCALE_DEFAULT);
        iconCookie = new ImageIcon(newimg);

        ImageIcon iconChicken = new ImageIcon(new URL("https://i.stack.imgur.com/qJA7G.gif"));
        Image chickenimage = iconChicken.getImage();
        Image newimgc = chickenimage.getScaledInstance(250, 250, Image.SCALE_DEFAULT);
        iconChicken = new ImageIcon(newimgc);

        chicken = iconChicken.getImage();
        cookie = iconCookie.getImage();
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(() -> new Chicken());
    

代码有问题吗?还是有另一种方法可以做到这一点,而我只是做错了? gif 应该没问题,我自己创建的,当我从我的电脑上查看它们时它们看起来很好。

Chicken

Cookie

编辑

取出饼干后发现鸡肉没有闪烁,但我不知道为什么。

【问题讨论】:

@Override public void update(Graphics g) 为什么代码会覆盖该方法? 我将问题中的代码编辑为minimal reproducible example。 (这主要涉及到图像的热链接。)编辑后的代码是否在您的最后显示相同的问题?如果没有,请进入edit history 并回滚我所做的更改。 “我自己创建的..” 就是这样..Image newimgc = chickenimage.getScaledInstance(250, 250, Image.SCALE_DEFAULT); 缩放图像的最佳时间是之前 它们由应用程序加载! 你好@AndrewThompson! @Override public void update(Graphics g) 老实说我不太确定,我们在学校被教导要这样做。还有其他方法吗?还是我应该删除@Override?我已经尝试过您的更改,但遗憾的是它似乎没有任何区别。还在闪烁。我想我只需将 cookie.gif 更改为似乎可以处理闪烁的 .png。非常感谢您的回答! “或者我应该删除@Override吗?” 删除整个方法。改变现有的功能并没有什么好处。当我删除它时,我看不到鸡肉图像中的任何进一步闪烁。我还建议在该代码中进行其他更改,但没有这些更改。 【参考方案1】:

paintComponent 中删除setDoubleBuffered(true);。可能是诱人的代码。您可以在构造函数中调用它,但默认情况下双缓冲是打开的。将setBackground(Color.BLACK); 移动到构造函数中。

然后删除update方法。

您通常不需要致电super.paintComponent();。将其注释掉,并尝试查看更改。

您可以使用setContentPane(canvas)

如果还有问题,那就是gif处理的内部工作原理。

【讨论】:

“您通常不需要致电 super.paintComponent();。” 不过这是最佳做法。 您好!感谢您的答复!我都试过了。当我删除super.paintComponent(); 时,它会产生一种奇怪的效果,您可以在背景中看到之前的帧。也很遗憾,它并没有解决闪烁问题,但还是谢谢你! @AndrewThompson 是的,它负责正确的图形开关。对于闪烁,我想消除它的原因。 @ArvyMinsk 我希望更新重新实现。由于您的评估指向导致闪烁的第二个 gif,也许您应该尝试 JLayeredPane 和/或 OverlayLayout,因此两个双缓冲背景上有两个paintComponents。叹息。 You normally do not need to call super.paintComponent();. - 您应该始终调用 super.paintComponent() 以确保在进行任何自定义绘画之前清除背景,否则您可能会出现绘画伪影。

以上是关于GIF ImageIcon 在 Java Swing 中不断闪烁的主要内容,如果未能解决你的问题,请参考以下文章

java游戏制作之水果忍者

java用户界面——加载图片 jpg GIF

JFrame.setBackground(Color)修改ImageIcon大小

java中如何判断imageicon中的两张图片相等。

GUI起头

如何在java中添加一个ImageIcon?此代码不起作用