有些时候我们可能在J2ME中遇到画面闪烁的问题,这时候我们可以应用双缓冲的技术来解决,不过由于现在越来越多的手机自身就支持双缓冲了。所以这里只做个简单的介绍。
我写了程序本来想在NOkia 6108上比较用和不用的区别,结果这个手机自己就支持双缓冲,所以根本没有比较出来。不过了解这个技术还是有必要的,所以我决定还是写出来。双缓冲本来是在开发PC应用程序的时候遇到的。在MIDP开发中同样存在,当你在屏幕上进行原始写画的时候,如果很复杂的话,用户会发现界面在闪烁。因此你可以这样做,首先在另一个图片上进行paint()得操作,当完成了以后就把它copy到屏幕上,由于通常copy得时候速度很快就不会出现闪烁了。这个技术就是双缓冲。
Canvas类提供了isDoubleBuffered()方法来判断设备是不是支持这个功能,如果返回true的话,那么我们就没有必要使用双缓冲了,如果false的话,我们可以这么做:
public DoubleCanvas(UIController uicontroller)
{
super();
this.uicontroller = uicontroller;
width = this.getWidth();
height = this.getHeight();
this.setCommandListener(this);
if(!isDoubleBuffered())
{
offImage = Image.createImage(width,height);
}
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.Displayable#paint(javax.microedition.lcdui.Graphics)
*/
protected void paint(Graphics arg0)
{
// TODO Auto-generated method stub
arg0.drawString(isDoubleBuffered()+"",width/2,height/2,Graphics.HCENTER|Graphics.TOP);
Graphics saved = arg0;
if(offImage != null)
{
arg0 = offImage.getGraphics();
}
arg0.setColor(255,128,128);
for(int i = 2,j=2;i<width/2-6&&j<height/2-6;i=i+2,j=j+2)
{
arg0.drawRect(i,j,width-2*i,height-2*j);
}
if(arg0 != saved)
{
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);
}
}
得到offImage得Graphics实例后,进行paint()得操作。这个部分通常比较复杂,我这里的不够复杂:)
然后把offImage直接copy到屏幕上也就是执行saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);
我写了一个应用程序来比较使用和不使用双缓冲的效果,但是由于我的手机支持双缓冲所以看不出效果,如果你有兴趣,那么可以把paint()部分的代码修改的复杂一些然后再移植到不支持的手机上也许可以看出效果,下面是我程序的代码:
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
/*
* Created on 2004-7-3
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author P2800
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class DoubleBufferMIDlet extends MIDlet
{
private UIController uicontroller;
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#startApp()
*/
protected void startApp() throws MIDletStateChangeException
{
// TODO Auto-generated method stub
uicontroller = new UIController(this);
uicontroller.init();
}
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#pauseApp()
*/
protected void pauseApp()
{
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
*/
protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
// TODO Auto-generated method stub
}
}
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
/*
* Created on 2004-7-3
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author P2800
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class MainListUI extends List implements CommandListener
{
//private DoubleBufferMIDlet doubleMIDlet;
private UIController uicontroller;
public MainListUI(UIController uicontroller)
{
super("Test",List.IMPLICIT);
this.uicontroller = uicontroller;
this.append("Non-buffer",null);
this.append("Double-buffer",null);
this.setCommandListener(this);
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
*/
public void commandAction(Command arg0, Displayable arg1)
{
// TODO Auto-generated method stub
if(arg0 == List.SELECT_COMMAND)
{
if(this.getSelectedIndex() == 0)
{
uicontroller.handleEvent(UIController.EventID.DISPLAY_NON_BUFFER);
}
else
{
uicontroller.handleEvent(UIController.EventID.DISPLAY_BUFFER);
}
}
}
}
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
/*
* Created on 2004-7-3
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author P2800
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class UIController implements CommandListener
{
private Display display;
private DoubleBufferMIDlet midlet;
private MainListUI mainList;
private NonDoubleCanvas noDoubleCanvas;
private DoubleCanvas doubleCanvas;
public static final Command backCommand = new Command("Back",Command.BACK,2);
public static class EventID
{
public static final int DISPLAY_NON_BUFFER = 0;
public static final int DISPLAY_BUFFER = 1;
}
/**
*
*/
public UIController(DoubleBufferMIDlet midlet)
{
this.midlet = midlet;
// TODO Auto-generated constructor stub
}
public void init()
{
display = Display.getDisplay(midlet);
mainList = new MainListUI(this);
noDoubleCanvas = new NonDoubleCanvas(this);
doubleCanvas = new DoubleCanvas(this);
addCommand();
display.setCurrent(mainList);
}
public void addCommand()
{
noDoubleCanvas.addCommand(backCommand);
doubleCanvas.addCommand(backCommand);
}
public Display getDisplay()
{
return display;
}
public void setCurrent(Displayable disp)
{
display.setCurrent(disp);
}
public void handleEvent(int eventID)
{
switch(eventID)
{
case EventID.DISPLAY_BUFFER:
{
setCurrent(doubleCanvas);
System.out.println(EventID.DISPLAY_BUFFER);
break;
}
case EventID.DISPLAY_NON_BUFFER:
{
setCurrent(noDoubleCanvas);
System.out.println(EventID.DISPLAY_NON_BUFFER);
break;
}
}
}
public void commandAction(Command arg0, Displayable arg1)
{
// TODO Auto-generated method stub
if(arg0 == backCommand)
{
display.setCurrent(mainList);
}
}
}
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
/*
* Created on 2004-7-3
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author P2800
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class NonDoubleCanvas extends Canvas implements CommandListener
{
//private DoubleBufferMIDlet midlet;
private UIController uicontroller;
private int width;
private int height;
/**
*
*/
public NonDoubleCanvas(UIController uicontroller)
{
super();
this.uicontroller = uicontroller;
width = this.getWidth();
height = this.getHeight();
this.setCommandListener(this);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.Displayable#paint(javax.microedition.lcdui.Graphics)
*/
protected void paint(Graphics arg0)
{
// TODO Auto-generated method stub
arg0.setColor(100,100,100);
arg0.drawString(isDoubleBuffered()+"",width/2,height/2,Graphics.HCENTER|Graphics.TOP);
for(int i = 2,j=2;i<width/2-6&&j<height/2-6;i=i+2,j=j+2)
{
arg0.drawRect(i,j,width-2*i,height-2*j);
}
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
*/
public void commandAction(Command arg0, Displayable arg1)
{
// TODO Auto-generated method stub
uicontroller.commandAction(arg0,arg1);
}
}
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/*
* Created on 2004-7-3
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author P2800
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class DoubleCanvas extends Canvas implements CommandListener
{
//private DoubleBufferMIDlet midlet;
private UIController uicontroller;
private Image offImage;
private int width;
private int height;
/**
*
*/
public DoubleCanvas(UIController uicontroller)
{
super();
this.uicontroller = uicontroller;
width = this.getWidth();
height = this.getHeight();
this.setCommandListener(this);
if(!isDoubleBuffered())
{
offImage = Image.createImage(width,height);
}
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.Displayable#paint(javax.microedition.lcdui.Graphics)
*/
protected void paint(Graphics arg0)
{
// TODO Auto-generated method stub
arg0.drawString(isDoubleBuffered()+"",width/2,height/2,Graphics.HCENTER|Graphics.TOP);
Graphics saved = arg0;
if(offImage != null)
{
arg0 = offImage.getGraphics();
}
arg0.setColor(255,128,128);
for(int i = 2,j=2;i<width/2-6&&j<height/2-6;i=i+2,j=j+2)
{
arg0.drawRect(i,j,width-2*i,height-2*j);
}
if(arg0 != saved)
{
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);
}
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
*/
public void commandAction(Command arg0, Displayable arg1)
{
// TODO Auto-generated method stub
uicontroller.commandAction(arg0,arg1);
}
}