|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionHave you ever created an application that showed an animation in your window? You probably have, and if you have not, you probably will someday. The coding is really simple: you take a No, it's not quiet over yet. Because, if you leave it like that, the screen will flash and flicker, and your animation will end up partially painted, or not painted at all. The solution for this is the infamous double buffer. AWT versus SWINGIn the Swing framework, you can add the double buffer just by setting this property to true in your class. Swing is carrying out all of the tasks needed for you. They're behind the scenes, and all that you have to know is that it's done. The flicker is gone. Thank you mister Sun. But what if you use the standard AWT? The Swing framework is rather heavy and still has some nasty bugs, so, on older machines, it's more likely that you use the standard AWT. But, there's no double buffer here, isn't it? I've studied this problem for some while now, and this is the solution I've come up with. It is a solution, not the solution. I've seen others too, but they all have more or less the same components. The DoubleBuffer ClassSince we are good Java programmers, we create a base-class for this, so we can implement the double buffer functionality whenever we feel like. You can choose between the classes import java.awt.*;
public class DoubleBuffer extends Panel{
public DoubleBuffer(){
super();
}
Eliminating the FlickerWhat's causing the flicker? Well, if you call the We're going to deprecate this. public void update(Graphics g){
paint(g);
public void paint(Graphics g){
}
Now, the background isn't cleared anymore, so the flicker is gone. If you use this to animate through some images with the same dimensions, you are finished here already, because you don't have to clear the previous image. But what if you have to clear the previous paintjob? The Buffer ImageThe idea behind double buffering is that you first paint everything to an off-screen image, and, when it's ready, paint it to the screen in just one paintjob. For this purpose, we need a // class variables
private int bufferWidth;
private int bufferHeight;
private Image bufferImage;
private Graphics bufferGraphics;
public void paint(Graphics g){
// checks the buffersize with the current panelsize
// or initialises the image with the first paint
if(bufferWidth!=getSize().width ||
bufferHeight!=getSize().height ||
bufferImage==null || bufferGraphics==null)
resetBuffer();
}
private void resetBuffer(){
// always keep track of the image size
bufferWidth=getSize().width;
bufferHeight=getSize().height;
// clean up the previous image
if(bufferGraphics!=null){
bufferGraphics.dispose();
bufferGraphics=null;
}
if(bufferImage!=null){
bufferImage.flush();
bufferImage=null;
}
System.gc();
// create the new image with the size of the panel
bufferImage=createImage(bufferWidth,bufferHeight);
bufferGraphics=bufferImage.getGraphics();
}
So, your public void paint(Graphics g){
... resetBuffer();
if(bufferGraphics!=null){
//this clears the offscreen image, not the onscreen one
bufferGraphics.clearRect(0,0,bufferWidth,bufferHeight);
//calls the paintbuffer method with
//the offscreen graphics as a param
paintBuffer(bufferGraphics);
//we finaly paint the offscreen image onto the onscreen image
g.drawImage(bufferImage,0,0,this);
}
}
public void paintBuffer(Graphics g){
//in classes extended from this one, add something to paint here!
//always remember, g is the offscreen graphics
}
Now, your double buffer class is ready! Extending the new classNow, everything you have to do is to extend public class MyBuffer extends DoubleBuffer{ private int posX; public MyBuffer(){ super(); posX=0; } public void animateToTheRight(){ // this can be called from everywhere, anytime posX++; repaint(); } // attention: we don't touch update() and paint() anymore // we use paintbuffer() instead public void paintBuffer(Graphics g){ /// g is the offscreen graphics g.drawString("Double Buffer!",posX,20); } } In the example, if you add a thread and let it call Voila, the double buffer is working.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||