`
wayfarer
  • 浏览: 298397 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

DoubleBuffer 实现

阅读更多

     绘制地图的时候会出现图片断裂,屏幕闪烁等绘图效率问题, 怎么办?双缓冲技术。实际上,在midp1.0中没有game包,也没有实现双缓冲。但有些设备本身就支持双缓冲(midp2.0自动实现了双缓冲),每次都是先把屏幕重画在缓冲之中,然后再绘制在显示屏幕上,而不是直接绘制在显示屏幕上。如果Canvas类下的DoubleBuffered()返回true, 则表示设备已实现了双缓冲。

    造成屏幕闪烁的主要原因在于,画面在显示的同时程序又在改变它,于是画面闪烁。解决办法是在内存中开辟一片区域作为后台画面,程序对它更新、修改,完成后再显示它。这样被显示的图像永远是已经完全画好的图像,程序修改的将不是正在被显示的图像。

 

     原理:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到实际的黑板(屏幕)上。即先在一个图片(可变图像:可以很好的用作屏幕外缓冲)上进行paint()得操作,当完成了以后就把它copy到屏幕上,由于通常copy得时候速度很快就不会出现闪烁了。
     具体过程:按屏幕大小建立一个缓冲对象bufferImage(必须是可变Image);然后Graphics g = bufferImage.getGraphics(),最后用g绘制图片到缓冲对象bufferImage中,将所有的绘制都放在可变图像中;最后通过repaint()调用paint(Graphics g)将缓冲对象bufferImage绘制到真实屏幕上。

 

package forrest.doublebuffer;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 * 实现双缓冲的Game画布。实现原理是创建一个BufferImage。然后绘制,最后显示出来。就这么简单。
 */
public abstract class DoubleBuffer extends Canvas {
	private Image bufferImage; // 绘制缓冲的图片,即黑板。用户绘制资源的时候都是操作这个图片来进行的。
	private int clipX, clipY, clipWidth, clipHeight;
	private boolean isSetClip;
	
	protected DoubleBuffer() {
		bufferImage = Image.createImage(getWidth(), getHeight());
	}
	
	protected void paint(Graphics g) {
		// 对指定区域进行DoubleBuffer
		if (isSetClip) {
			g.clipRect(clipX, clipY, clipWidth, clipHeight);
			isSetClip = false;
		}
		g.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT);
	}
	
	public void flushGraphics() {
		repaint();
		serviceRepaints();
	}
	
	public void flushGraphics(int x, int y, int w, int h) {
		isSetClip = true;
		clipX = x;
		clipY = y;
		clipWidth = w;
		clipHeight = h;
		
		repaint();
		serviceRepaints();
	}
	
	/**
	 * Designer will get the picture through invoking this method, then paint this picture.
	 * */
	protected Graphics getGraphics() {
		return bufferImage.getGraphics();
	}
	
	/**
	 * For nokia platform,when user invoke setFullScreenMode(boolean enable), create 
        * new buffered picture based on parameter: w and h.
	 * */
	protected final void sizeChanged(int w, int h) {
		if (h > getHeight()) {
			bufferImage = Image.createImage(w, h);
		}
	}
}

 

package forrest.doublebuffer;

import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class DoubleBuffer extends Canvas {
	private Image bufferImage, //mutable picture,作为绘制缓冲
				  img; // 不变picture,用来load图片文件
	public DoubleBuffer() throws IOException {
		img = Image.createImage("/img.png");
		bufferImage = Image.createImage(getWidth(), getHeight()); // 用一个mutable picture作为绘制缓冲
		Graphics g = bufferImage.getGraphics();
		g.setColor(0xffffff);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(img, getWidth() / 2, getHeight() / 2, Graphics.VCENTER | Graphics.HCENTER);
	}
	protected void paint(Graphics g) {
		g.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT); // g: 屏幕画笔,将缓冲区上的内容绘制到屏幕上
	}
	
}

 

package forrest.doublebuffer;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class DoubleBuffer extends Canvas {
	private Image bufferImage;
	
	public DoubleBuffer() {
		if (!isDoubleBuffered()) {
			bufferImage = Image.createImage(getWidth(), getHeight());
		}
	}
	
	protected void paint(Graphics g) {
		Graphics temp = g;
		if (bufferImage != null) {
			g = bufferImage.getGraphics();
		}
		g.setColor(0xff0000);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(0xffffff);
		g.drawLine(0, 0, 100, 100);
		if (g != temp) {
			// 把bufferImage直接copy到屏幕上
			temp.drawImage(bufferImage, 0, 0, Graphics.TOP | Graphics.LEFT);
		}
	}
}
分享到:
评论

相关推荐

    doublebuffer

    在计算机图形学和软件开发中,"doublebuffer"是一种优化技术,主要用于提高图像显示的质量和流畅性,尤其是在处理复杂的动态图形时。双缓存技术利用了两个独立的内存区域,一个用于绘制图形,另一个用于显示,以此来...

    C#双缓冲实现方法(可防止闪屏)

    本篇文章将详细阐述C#中实现双缓冲的方法,并通过实例来解析其工作原理。 首先,我们来看一下双缓冲的基本概念。双缓冲技术涉及到两个主要的缓冲区:前台缓冲区和后台缓冲区。通常,前台缓冲区是直接与屏幕关联的,...

    基于MFC的文件目录树的对话框实现代码

    CTreeViewCtrl 类是MFC提供的,用于实现Windows的TVS_EX_DOUBLEBUFFER等风格的树形视图控件,它可以展示层次结构的数据,如文件系统目录结构。 1. **创建对话框类**: 首先,我们需要创建一个新的派生自`CDialog`...

    双缓存实现风车转动.rar

    本文将详细解析"双缓存实现风车转动"这一主题,主要针对C++编程语言。 首先,我们需要理解什么是双缓存。在计算机科学中,缓存是一种存储层次结构,用于临时存储频繁访问的数据,以减少主内存或硬盘的访问时间。双...

    双缓冲绘图 模板类 demo

    例如,DoubleBufferView.cpp和DoubleBuffer.cpp可能包含了双缓冲视图类和文档类的实现,这两个类是MFC(Microsoft Foundation Classes)框架中的重要组件,分别负责处理用户界面的显示和数据存储。 ...

    C#,winform,gdi+,简单实现鼠标拉出虚线框,适合初学者

    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true); } ``` 2. **鼠标按下**:在`MouseDown`事件中,存储鼠标点击时的位置。 ```csharp private Point...

    C# 实现draw一个简单的温度计

    上述代码实现了一个 TemperatureGauge 控件,该控件主要包含以下几个部分: 属性定义: MinValue:最低温度值。 MaxValue:最高温度值。 CurrentValue:当前温度值。 构造函数: 设置了一些控件样式来提升绘制...

    threadSafeBuffer:用C ++实现的线程安全双缓冲示例

    一个C++实现的线程安全的双缓冲实例 scenario: a multithreaded business system writes data to memory, while a synchronous thread reads data and synchronizes to redis. 场景:多线程的业务系统不断写入数据到...

    .net实现鼠标拖拽,类似CAD、visio的功能.zip

    - 为了提高性能,可以开启双缓冲,通过`SetStyle(ControlStyles.DoubleBuffer, true)`避免闪烁。 6. **图形状态管理**: - 在拖动过程中,图形可能处于“被拖动”状态,需要在数据结构中保存这种状态,以便在鼠标...

    在VisualC_6_0环境下利用OpenGL实现模型的动态观察

    PFD_DOUBLEBUFFER, // 双缓冲 PFD_TYPE_RGBA, // RGBA模式 24, // 颜色缓冲区深度 0, 0, 0, 0, 0, 0, // 不使用Alpha缓冲区 0, // 不使用累积缓冲区 0, 0, 0, 0, // 不使用辅助位平面 0, // 不使用层掩码 0,...

    计算机图形学编程练习8MFC-明暗处理实现.doc

    PFD_DOUBLEBUFFER, // 双缓冲模式 PFD_TYPE_RGBA, // RGBA颜色模式 24, // 颜色位数 0, 0, 0, 0, 0, 0, // 不使用选择模式 0, 0, // 不使用选择模式 0, 0, 0, 0, 0, // 不使用选择模式 32, // 深度缓冲区大小...

    C#实现的渐变的窗体背景

    this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); ``` 至此,我们已经成功地使用C#和VS.NET创建了一个具有渐变背景的窗体。你可以根据需要调整...

    Liang-Barsky直线段裁剪算法.docx

    5. **双缓冲机制**:实现`DoubleBuffer`函数,通过双缓冲技术减少屏幕闪烁,提高绘图性能。 6. **坐标转换**:实现`Convert`函数,用于完成从设备坐标系到窗口坐标系的转换。 7. **裁剪窗口绘制**:实现`DrawRect`...

    C#绘图双缓冲技术总结

    在 .NET 1.1 中,使用 `this.SetStyle(ControlStyles.DoubleBuffer, true);` 可以实现双缓冲,而在 .NET 2.0 中,需要使用 `this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);`。 双缓冲技术的关键在于,...

    c++ 下利用waveOutWrite(directsound)编写的双缓冲区音频播放程序

    在这个特定的项目"PCMPlay_doublebuffer"中,我们可以预期包含以下几个关键部分: 1. **音频数据结构**:程序需要定义适当的结构来存储音频数据,通常是以PCM格式,包括采样率、位深度和通道数等信息。 2. **波形...

    VC利用双缓存解决闪屏

    本文将详细介绍如何在VC++6.0环境下利用双缓存来消除界面的闪烁现象,并通过源码和详细注释来帮助理解其实现过程。 双缓冲是一种图形渲染技术,它的核心思想是先在内存中的一个“缓冲区”(后台缓冲区)绘制整个...

    模拟时钟 word文档

    在关键源代码中,我们看到了双缓冲函数`DoubleBuffer()`和绘制函数`DrawObject()`的具体实现。这两个函数是实现模拟时钟的核心部分,它们确保了图形的正确显示和流畅的动画效果。`DrawObject()`中不仅绘制了钟面,还...

    基于VC的大鱼吃小鱼游戏

    5. **双缓冲技术(DoubleBuffer)**:压缩包中的"DoubleBuffer"可能是指双缓冲图形技术,这是为了避免屏幕闪烁,提高游戏画面更新的流畅性。双缓冲技术是在内存中创建一个额外的位图,先在位图上完成所有的绘图操作,...

    C#中在pictureBox1中实时画矩形框.

    根据给定的信息,本文将详细解释如何在C#中使用`pictureBox1`控件实现实时绘制矩形框的功能。 ### 一、基础知识 #### PictureBox 控件简介 `PictureBox` 控件是Windows Forms 应用程序中用于显示图像的一个控件。...

Global site tag (gtag.js) - Google Analytics