I'm sure you recognized in the first applet that the circle is flickering. There is a very simple reason for this. Everytime the paint - method is called by repaint() the applet screen is cleared completly. Because of this we can see for a millisecond a absolutly blank screen. To suppress this phenomena, we have three possibilities:
- We don't clear the screen at all
- We clear the screen only where something is changing
- We use double buffering
Don't clear the screen at all
This idea seems to be the solution to all our problems (but it is not!). In our case it would mean that the ball would paint a thick red line across the applet because the screen stays red at every position the ball has been once. This might be ok for some situations but we want to see a moving ball, not a thick red line. So this technique is just useful for objects that are not moving.
At first it is important for you to know one thing. The call of repaint() doesn't call the paint() - method at the same time. Instead, a method called update() is called. If one doesn't overwrite this method, update() clears the complete screen and afterwards calls paint() which paints the background and our circle again. To avoid clearing the screen you have to overwrite the update() - method. Our new update() - method doesn't clear the screen anymore, but just calls paint(). This can be done with three line of code:
public void update(Graphics g)
As I said before this is no solution for our applet. But it is essential to understand that repaint() doesn't call paint() but update() which then calls paint()!
Clear the screen only where something is changing
This solution is based on the idea to repaint just those parts of our applet where something has changed. This concept is very good for a game like snakin'. If the last part of your snake is colored in the same color as the background, this part overpaints the parts of the snake, where the snake has been. I don't want to talk about this solution in detail, because one sould use this method just in very special situations. So let's talk about the double buffering which is a really good and effective solution to avoid a flickering screen and the best of it all: You can use this method in every applet the same way as I do now, so you'll never have to worry about that problem again!
As I said you can use double buffering in every applet in a very easy way. Double buffering means to paint all the things in the paint() method to an offscreen image. If all things that have to be painted, are painted, this image is copied to the applet screen. The method does the following in detail:
- Generates a new offscreen-image by using createImage and stores this image in a instance variable( = generate an empty image)
- Call getGraphics to get graphic context for this image
- Draw everything (including to clear the screen completely) on the offscreen image ( = draw image in the background)
- When finished, copy this image over the existing image on the screen. ( = draw image in the foreground)
This technique means that the picture is already painted before it is copied to the screen. When copiing the image to the foreground the old pixels are overlayed by the new ones. There won't be any flickering picture anymore because there is not a millisecond where you see an empty screen!
The only disadvantage of the double buffering is, that it produces a large amount of data and every image is drawn two times (offscreen and when copying to the screen). But in most cases and on a fast computer this is much better than wasting time on finding an other solution!
Well after all this theory I will show you how to integrate the double buffering into our "ball moving" applet (use the applet of the chapter before as basic code!):
Double buffering: the code
// declare two instance variables at the head of the program
private Image dbImage;
private Graphics dbg;
... other code ...
/** Update - Method, implements double buffering */
public void update (Graphics g)
dbImage = createImage (this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics ();
// initialize buffer
if (dbImage == null)
// clear screen in background
dbg.setColor (getBackground ());
dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
// draw elements in background
// draw image on the screen
g.drawImage (dbImage, 0, 0, this);
As I said before you can copy and paste this code into every applet that uses animations!