欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用双缓冲技术解决动画播放闪烁问题

程序员文章站 2022-07-05 12:35:14
...

双缓冲技术主要就是使多张图像在后台绘制到一张图像上,然后把这一张图像绘制到显示屏幕上来解决多次绘制导致的屏幕闪烁

就比如如下的方法,传入系统屏幕的画笔g,然后在后台上创建一个和屏幕一样大的图像iBuffer,再获得iBuffer的画笔gBuffer,

通过画笔gBuffer把图像画到iBuffer上面,这就是在后台完成图像的绘制,最终调用系统的画笔g把后台绘制完成的图像画到屏幕上

/**
	 * 绘制方法
	 * 采用双缓冲技术
	 */
	public void onDrow(Graphics g) {
		//判断后台图像是否为空  
		if(iBuffer == null){  
			//如果为空,则创建一个和当前界面一样大小的缓冲图像,再取得这个图像的画布对象gBuffer  
			iBuffer = createImage((int)this.getSize().getWidth(),(int)this.getSize().getHeight());  
		}
		//获得该图像的画笔
		gBuffer = iBuffer.getGraphics();  
		//用背景色填充图像(清理画面) 
		//一般如果有背景图的话,本段就可以不用了
		gBuffer.setColor(getBackground());  
		gBuffer.fillRect(0, 0, (int)this.getSize().getWidth(), (int)this.getSize().getHeight()); 
		
		gBuffer.drawImage(image.getSubimage(ax, ay, w, h), 1000, 300, 50, 75, null);
		
		//在界面上直接画出缓冲图像  
		g.drawImage(iBuffer,0,0,this); 
	}

最终贴上完整代码,其中的图片可以酌情换成其他4*4的人物行走素材图片
package com.ljxt.SwingTest;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class SwingTest extends JFrame{	
	
	public static int count = 0;
	
	public static int screenWidth;
	public static int screenHeight;
	
	public static BufferedImage image;
	
	boolean isRun = true;

	Image iBuffer;
	Graphics gBuffer;
	static int ax = 0;
	int ay = 0;
	int w;
	int h;
	
	public static void main(String[] args) {
		//初始化设置
		SwingTest swingTest = new SwingTest(true);
		//显示窗体
		swingTest.setVisible(true);
		//开始循环绘制
		swingTest.action();
		
	}
	
	/**
	 * 开启线程
	 */
	public void action() {
		new Thread(run).start();
	}
	
	/**
	 * 绘制图像
	 */
	public void paint(Graphics g) {
		//调用绘制方法
		onDrow(g);
	}
	
	/**
	 * 绘制方法
	 * 采用双缓冲技术
	 */
	public void onDrow(Graphics g) {
		//判断后台图像是否为空  
		if(iBuffer == null){  
			//如果为空,则创建一个和当前界面一样大小的缓冲图像,再取得这个图像的画布对象gBuffer  
			iBuffer = createImage((int)this.getSize().getWidth(),(int)this.getSize().getHeight());  
		}
		//获得该图像的画笔
		gBuffer = iBuffer.getGraphics();  
		//用背景色填充图像(清理画面) 
		//一般如果有背景图的话,本段就可以不用了
		gBuffer.setColor(getBackground());  
		gBuffer.fillRect(0, 0, (int)this.getSize().getWidth(), (int)this.getSize().getHeight()); 
		
		gBuffer.drawImage(image.getSubimage(ax, ay, w, h), 1000, 300, 50, 75, null);
		
		//在界面上直接画出缓冲图像  
		g.drawImage(iBuffer,0,0,this); 
	}
	
	/**
	 * 读取图片
	 */
	public void getImage() {
		if(image == null) {
			try {
				image = (BufferedImage)(ImageIO.read(new FileInputStream("image/人物行走.jpg")));
				//获得图片截取的大小
				w = image.getWidth() / 4;
				h = image.getHeight() / 4;
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	
	/**
	 * 更新画面
	 */
	public void update(Graphics g){  
		paint(g);  			
	}
	
	/**
	 * 获得屏幕大小
	 */
	public void getScreen() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension dimension = toolkit.getScreenSize();
		screenWidth = (int) dimension.getWidth();
		screenHeight = (int) dimension.getHeight();
		
	}
	
	/**
	 * 初始化窗体设置
	 */
	public SwingTest(boolean actMoving) {
		getImage();
		getScreen();
		setTitle("无限恐怖v0.1");
		setSize(screenWidth, screenWidth);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//设定背景为黑色
		setBackground(Color.BLACK);
	}
	
	/**
	 * 由线程来控制绘制频率
	 */
	Runnable run = new Runnable() {
		
		@Override
		public void run() {
			while (true) {
				if(SwingTest.count % 4 == 0) {
					ay = SwingTest.count / 4 * 75;
					ax = 0;
				}
				repaint();
				try {
					Thread.sleep(1000 / 10);
				} catch (Exception e) {
					
				}
				ax += w;
				SwingTest.count++;
				if(SwingTest.count == 4) {
					SwingTest.count = 0;
				}
				
			}
		}
	};
}