Chapter: Java The Complete Reference - The Java Library - Images

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Double Buffering

Not only are images useful for storing pictures, as we’ve just shown, but you can also use them as offscreen drawing surfaces.

Double Buffering

 

Not only are images useful for storing pictures, as we’ve just shown, but you can also use them as offscreen drawing surfaces. This allows you to render any image, including text and graphics, to an offscreen buffer that you can display at a later time. The advantage to doing this is that the image is seen only when it is complete. Drawing a complicated image could take several milliseconds or more, which can be seen by the user as flashing or flickering. This flashing is distracting and causes the user to perceive your rendering as slower than it actually is. Use of an offscreen image to reduce flicker is called double buffering, because the screen is considered a buffer for pixels, and the offscreen image is the second buffer, where you can prepare pixels for display.

 

Earlier in this chapter, you saw how to create a blank Image object. Now you will see how to draw on that image rather than the screen. As you recall from earlier chapters, you need a Graphics object in order to use any of Java’s rendering methods. Conveniently, the Graphics object that you can use to draw on an Image is available via the getGraphics( ) method. Here is a code fragment that creates a new image, obtains its graphics context, and fills the entire image with red pixels:

 

 

Canvas c = new Canvas();

 

Image test = c.createImage(200, 100); Graphics gc = test.getGraphics(); gc.setColor(Color.red); gc.fillRect(0, 0, 200, 100);

 

Once you have constructed and filled an offscreen image, it will still not be visible. To actually display the image, call drawImage( ). Here is an example that draws a time-consuming image to demonstrate the difference that double buffering can make in perceived drawing time:

 

/*

 

     <applet code=DoubleBuffer width=250 height=250>

 

     </applet>

 

*/

 

import java.awt.*; import java.awt.event.*; import java.applet.*;

 

public class DoubleBuffer extends Applet { int gap = 3;

 

int mx, my;

 

boolean flicker = true; Image buffer = null; int w, h;

 

public void init() { Dimension d = getSize(); w = d.width;

 

h = d.height;

 

buffer = createImage(w, h); addMouseMotionListener(new MouseMotionAdapter() {

 

public void mouseDragged(MouseEvent me) { mx = me.getX();

 

my = me.getY(); flicker = false; repaint();

 

}

 

public void mouseMoved(MouseEvent me) { mx = me.getX();

 

my = me.getY(); flicker = true;

 

repaint();

 

}

 

});

 

}

 

public void paint(Graphics g) { Graphics screengc = null;

 

if (!flicker) { screengc = g;

g = buffer.getGraphics();

 

}

 

g.setColor(Color.blue); g.fillRect(0, 0, w, h);

 

g.setColor(Color.red); for (int i=0; i<w; i+=gap)

 

g.drawLine(i, 0, w-i, h); for (int i=0; i<h; i+=gap)

g.drawLine(0, i, w, h-i);

 

g.setColor(Color.black);

 

g.drawString("Press mouse button to double buffer", 10, h/2);

 

g.setColor(Color.yellow);

 

g.fillOval(mx - gap, my - gap, gap*2+1, gap*2+1);

 

if (!flicker) { screengc.drawImage(buffer, 0, 0, null);

 

}

 

}

 

public void update(Graphics g) { paint(g);

 

}

 

}

 

This simple applet has a complicated paint( ) method. It fills the background with blue and then draws a red moiré pattern on top of that. It paints some black text on top of

that and then paints a yellow circle centered at the coordinates mx, my. The mouseMoved( ) and mouseDragged( ) methods are overridden to track the mouse position. These methods are identical, except for the setting of the flicker Boolean variable. mouseMoved( ) sets flicker to true, and mouseDragged( ) sets it to false. This has the effect of calling repaint( ) with flicker set to true when the mouse is moved (but no button is pressed) and set to false when the mouse is dragged with any button pressed.

When paint( ) gets called with flicker set to true, we see each drawing operation as it is executed on the screen. In the case where a mouse button is pressed and paint( ) is called with flicker set to false, we see quite a different picture. The paint( ) method swaps the Graphics reference g with the graphics context that refers to the offscreen canvas, buffer, which we created in init( ). Then all of the drawing operations are invisible. At the end of paint( ), we simply call drawImage( ) to show the results of these drawing methods all at once.


Figure 27-2   Output from DoubleBuffer without (left) and with (right) double buffering

 

Notice that it is okay to pass in a null as the fourth parameter to drawImage( ). This is the parameter used to pass an ImageObserver object that receives notification of image events. Since this is an image that is not being produced from a network stream, we have no need for notification. The left snapshot in Figure 27-2 is what the applet looks like with the mouse button not pressed. As you can see, the image was in the middle of repainting when this snapshot was taken. The right snapshot shows how, when a mouse button is pressed, the image is always complete and clean due to double buffering.

 


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.