Java 桌面精灵关键代码

参考:http://blog.csdn.net/kai_wei_zhang/article/details/8120382

http://www.cnblogs.com/S-E-P/archive/2010/01/27/2045076.html

一、闪烁的原因

动画就是一帧一帧的切换图片。

每次切换都会先用背景色覆盖组件再重绘图像,如此就造成了两帧之间的空白画面。从而导致了闪烁。

注意,这个repaint()函数是从Frame类继承而来的。它先调用update(Graphics g)函数,update(Graphics g)再调用paint(Graphics g)函数

 二、解决方案 

背景色覆盖、绘图都在内存中进行,最后一次性画到控件上。

也就是我们所说的双缓冲技术。

Frame (收集自网络未实验)

Image ImageBuffer = null;  
Graphics GraImage = null;  
  
public void update(Graphics g){     //覆盖update方法,截取默认的调用过程  
    ImageBuffer = createImage(this.getWidth(), this.getHeight());   //创建图形缓冲区  
    GraImage = ImageBuffer.getGraphics();       //获取图形缓冲区的图形上下文  
    paint(GraImage);        //用paint方法中编写的绘图过程对图形缓冲区绘图  
    GraImage.dispose();     //释放图形上下文资源  
    g.drawImage(ImageBuffer, 0, 0, this);   //将图形缓冲区绘制到屏幕上  
}  
  
public void paint(Graphics g){      //在paint方法中实现绘图过程  
    g.drawLine(0, 0, 100, 100);  
}  

JFrame 

在这里说一下,上面所说的不知为啥,我的Update总是 不能调用,怀疑JDK版本更新后,update调用被改变了。

参考自网上

	private Image iBuffer;
	public void paint(Graphics scr) {
		if (iBuffer == null)
			iBuffer = createImage(this.getSize().width, this.getSize().height);

		Graphics gBuffer = iBuffer.getGraphics();

		gBuffer.setColor(getBackground());
		gBuffer.fillRect(0, 0, this.getSize().width, this.getSize().height);
		gBuffer.setColor(Color.RED);
		gBuffer.fillOval(90, ypos, 80, 80);
		scr.drawImage(iBuffer, 0, 0, this);
	}

例子:实现透明窗体动画效果(好像Swing自带双缓冲技术)。

但是如果在动画上方添加动态String,会失败。

public class Test5 extends JFrame {	
	private int nowFrame;   //当前帧	
	private Timer timer;	//定时器每隔几秒换张图
	private Image iBuffer = null;  //在内存中创建一个图对象
	private Image[] img;
	public Test5() {
		Toolkit toolkit=getToolkit();
		for(int i=0;i<img.length;i++){
			img[i]=toolkit.getImage("tupian"  + i + ".gif");
		}
		this.setAlwaysOnTop(true);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setVisible(true);
		this.setIconImage(SoftIcons.ICON_IMG);
		
		// 设置窗体透明
		this.setUndecorated(true);
		this.setBackground(new Color(0, 0, 0,0));// alpha分量为零
		
		//每隔0.1秒重绘一次窗口
		this.timer = new Timer(100, null);
		timer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				repaint();
			}
		});
		timer.start();
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		gBuffer.drawImage(img[nowFrame],30,100, null);
		if (nowFrame == icons.DANCE_IMG.length - 1) {
			nowFrame = 1;
		}
	}
	public static void main(String[] args) {
		new Test5();
	}
}

改进之后,可以在动画上方添加动态String,窗口透明

public class Test extends JFrame {
	private Timer timer;	
	private myPanel panel;

	public Test() {
		panel = new myPanel();	

		// 设置窗体透明
		this.setUndecorated(true);
		this.setBackground(new Color(0, 0, 0,0));// alpha分量为零

		// 设置窗体永远在前
		this.setAlwaysOnTop(true);
		this.setContentPane(panel);
		this.setSize(300, 400);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);		
		this.setIconImage(SoftIcons.ICON_IMG);
		this.setVisible(true);
		
		this.timer = new Timer(100, null);
		timer.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				panel.repaint();
			}
		});
		timer.start();
	}
	public static void main(String[] args) {
		new Test();
	}
	
	class myPanel extends JPanel{
		private int nowFrame;  //当前帧 
		private int behavior;
		private Image[] img;
		private String[] word;
		public myPanel() {
			this.setOpaque(false);
		}
		@Override
		public void paint(Graphics g) {
			// TODO Auto-generated method stub
			super.paint(g);
			g.drawString(word[behavior++], 20, 20);
			g.drawImage(img[nowFrame++],0,50, null);
			if (nowFrame == img.length - 1) 
				nowFrame = 0;
			if (behavior == word.length - 1) 
				behavior = 0;
		}
	}
}



因为大部分绘图过程是在内存中进行,所以有效地消除了闪烁。这应用了“以空间换取时间”和“功能分块”的思想


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值