JPanel绘制多张Image图片时,绘制的图片出现错乱怎么回事

JPanel绘制多张Image图片时,实现动态效果时,多线程调用repaint(),绘制的图片出现错乱怎么回事?哪位大神有空帮忙指点一二,不胜感激。

材料图片:

 

代码如下: 

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Description: Test
 * Created by yjh on 2021/2/19 18:08
 */
public class Test {

    public static void main(String[] args) throws IOException {
        JFrame jFrame = new JFrame();
        jFrame.setSize(480,480);
        jFrame.setLocationRelativeTo(null);// 设置 JFrame 窗口置于屏幕的中央
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭退出

        int cs = 32;
        final int[] imgStatus = {0};
        JPanel jPanel1 = new JPanel(null){
            // 图片
            Image image100 = ImageIO.read(new File("D:/aaa/100.png"));
            Image image102 = ImageIO.read(new File("D:/aaa/102.png"));

            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g;
                g2.setPaint(Color.black);// 背景颜色
                g2.fillRect(0, 0, getWidth(), getHeight());
                for (int y = 0; y < 15; y++) {
                    for (int x = 0; x < 15; x++) {
                        if (x<8)
                            g.drawImage(image100,x*cs,y*cs,x*cs+cs,y*cs+cs,
                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
                        else
                            g.drawImage(image102,x*cs,y*cs,x*cs+cs,y*cs+cs,
                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
                    }
                }
            }
        };
        jPanel1.setPreferredSize(new Dimension(480,480));
        jFrame.add(jPanel1);
        jFrame.setVisible(true);

        int top = jFrame.getInsets().top;// 获取菜单栏的高度
        int bottom = jFrame.getInsets().bottom;
        int left = jFrame.getInsets().left;
        int right = jFrame.getInsets().right;
        jFrame.setSize(480+left+right,480+top+bottom);
        jFrame.repaint();

        ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();//创建一个单个线程的线程
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if (imgStatus[0] >3){
                imgStatus[0] = 0;
                }
                imgStatus[0]++;
                jPanel1.repaint();
            }
        },0,500,TimeUnit.MILLISECONDS);// 0.5秒执行一次
    }
}

 

正常情况图片如下: 

 

 

执行等待一会就会出现,错乱了,变成红色的图片没有了,这个是怎么回事?怎么解决?:

 

 

你需要使用双缓存机制渲染。

@幻灰龙   听了你的建议,采用双缓冲技术并没有什么用 !-!

JPanel jPanel1 = new JPanel(null){
            Image iBuffer;
            Graphics2D gBuffer;

            // 图片
            Image image100 = ImageIO.read(new File("D:/aaa/100.png"));
            Image image102 = ImageIO.read(new File("D:/aaa/102.png"));

//            @Override
//            protected void paintComponent(Graphics g) {
//                Graphics2D g2 = (Graphics2D) g;
//                g2.setPaint(Color.black);// 背景颜色
//                g2.fillRect(0, 0, getWidth(), getHeight());
//                for (int y = 0; y < 15; y++) {
//                    for (int x = 0; x < 15; x++) {
//                        if (x<8)
//                            g.drawImage(image100,x*cs,y*cs,x*cs+cs,y*cs+cs,
//                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
//                        else
//                            g.drawImage(image102,x*cs,y*cs,x*cs+cs,y*cs+cs,
//                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
//                    }
//                }
//            }

            // 重写paint,采用双缓冲
            @Override
            public void paint(Graphics g){
                if (iBuffer == null){
                    iBuffer = createCompatibleImage(this.getSize().width,this.getSize().height);// 创建一个相同大小的缓冲图像
                    gBuffer = (Graphics2D) iBuffer.getGraphics();// 获取iBuffer的“逻辑画笔”
                }
                gBuffer.setPaint(Color.black);// 背景颜色
                gBuffer.fillRect(0, 0, getWidth(), getHeight());
                for (int y = 0; y < 15; y++) {
                    for (int x = 0; x < 15; x++) {
                        if (x<8)
                            gBuffer.drawImage(image100,x*cs,y*cs,x*cs+cs,y*cs+cs,
                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
                        else
                            gBuffer.drawImage(image102,x*cs,y*cs,x*cs+cs,y*cs+cs,
                                    imgStatus[0]*cs,0,imgStatus[0]*cs+cs,cs,this);
                    }
                }
                // 将 iBuffer 缓冲图像一次性绘制到 g 上(显示屏幕的Graphics)
                g.drawImage(iBuffer,0,0,this);
            }

            // 创建硬件适配的缓冲图像,为了能显示得更快速
            private BufferedImage createCompatibleImage(int w, int h) {
                GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice device = env.getDefaultScreenDevice();
                GraphicsConfiguration gc = device.getDefaultConfiguration();
                return gc.createCompatibleImage(w, h);
            }
        };

 

问题已解决了,不麻烦大家了。