Animation Basics
See the example applet in action in the demo or view the source code.Double Buffering
To help prevent this, a technique known as double buffering is used. First,
the update()
method is overridden to simply call
paint()
without erasing the current display.
Then, within paint(),
a new graphics context is created to act
as a buffer. The new display is drawn on this Graphics
object.
Once all the drawing is complete, the buffer is copied to the active
display.
// Off screen buffer. Dimension offDimension; Image offImage; Graphics offGraphics; ... public void update(Graphics g) { paint(g); } public void paint(Graphics g) { Dimension d = getSize(); Polygon poly; // Create the offscreen graphics context, if no good one exists. if (offGraphics == null || d.width != offDimension.width || d.height != offDimension.height) { offDimension = d; offImage = createImage(d.width, d.height); offGraphics = offImage.getGraphics(); } // Fill the applet background. offGraphics.setColor(Color.lightGray); offGraphics.fillRect(0, 0, d.width, d.height); // Rotate the shape for rendering; poly = rotate(shape, angle); // Draw the shape, centering it on the canvas. offGraphics.translate(d.width / 2, d.height / 2); offGraphics.setColor(Color.gray); offGraphics.fillPolygon(poly); offGraphics.setColor(Color.darkGray); offGraphics.drawPolygon(poly); offGraphics.translate(-d.width / 2, -d.height / 2); // Copy the off screen buffer to the screen. g.drawImage(offImage, 0, 0, this); } }
Using this technique, the applet display is updated in a single step. The individual drawing operations won't show since there is only one operation on the actual applet display, the copying of the buffer.
Note the use of both the Image
and Graphics
objects. Graphics
is an abstract class, you can't create an
instance directly. You can, however, create a new Image
and obtain
a graphics context from it using Image.getGraphics().
Creating a new graphics context requires some overhead, so global variables
are used rather than creating and destroying a new one every time
paint()
is called. The first part of the code,
// Create the off screen graphics context, if no good one exists. if (offGraphics == null || d.width != offDimension.width || d.height != offDimension.height) { offDimension = d; offImage = createImage(d.width, d.height); offGraphics = offImage.getGraphics(); }
both initializes the the off screen graphics context and ensures that it is the same size as the applet's current graphics context.