Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Platinum Edition Using HTML 4, XML, and Java 1.2
(Publisher: Macmillan Computer Publishing)
Author(s): Eric Ladd
ISBN: 078971759x
Publication Date: 11/01/98

Bookmark It

Search this book:
 
Previous Table of Contents Next


Fighting Flicker

You may have also noticed an annoying flicker in your animation program. This flicker occurs because a delay exists between the start of paint() and the time the image is actually loaded from the disk. You can eliminate the flicker by preloading the image into memory—a technique called double-buffering. Like the MediaTracker technique, double-buffering requires only a few lines of code. The following is a step-by-step procedure for adding double-buffering:

1.  Add an offscreen buffer and its graphics context to the list of instance variables:
Image fOffScreenImage;
Graphics fOffScreenGraphics;
2.  In init(), instantiate the offscreen buffer and paint it blue:
fOffScreenImage = createImage( getSize().width, getSize().height);
fOffScreenGraphics = fOffScreenImage.getGraphics();
fOffScreenGraphics.setColor(Color.blue);
fOffScreenGraphics.fillRect(0, 0, getSize().width, getSize().height);
3.  Override update(), which is responsible for clearing the background and calling paint():
public void update( Graphics g ) {
  fOffScreenGraphics.setColor(Color.blue);
  fOffScreenGraphics.clearRect(0, 0, getSize().width, getSize().height);
  fOffScreenGraphics.fillRect(0, 0, getSize().width, getSize().height);
  paint(g);
}
4.  Modify paint() so that it updates the offscreen image and draws the onscreen image from the offscreen image:
fOffScreenGraphics.drawImage(fEarth[i], 0, 0, this);
g.drawImage(fOffScreenImage, 0, 0, this);

Listing 39.17 shows the revised animation applet, with double-buffering and a MediaTracker. The new lines are shown in boldface font. You can use an HTML file to put the two applets up side-by-side, as a before-and-after demonstration. For smoothest performance, though, put Animation2 on a Web page without Animation1 so its thread doesn’t compete with Animation1’s thread.

Figure 39.16 shows a screen shot of an HTML page that shows all three versions of this applet—the original Animation1.java, a version with a MediaTracker, and a version that adds double-buffering.


AppletViewer’s performance with animation is sometimes poor. Use a Web browser such as Netscape Navigator (part of Netscape Communicator) to view these applets.


FIGURE 39.16  The Earth spins in three versions of the animation applet.

Listing 39.17 Animation2.javaThis Version of the Animation Applet is Noticeably Smoother and Is Flicker Free


 import java.awt.*;
 import java.applet.Applet;

 public class Animation2 extends Applet implements Runnable {
     int fFrame = -1;
     int fDelay;
     Thread fThread;
     Image[] fEarth;
     MediaTracker fTracker;
     Image fOffScreenImage;
     Graphics fOffScreenGraphics;

     public void init() {
       fEarth = new Image[30];
       String theString;
       int theFramesPerSecond = 10;
       fTracker = new MediaTracker( this );
       fOffScreenImage = createImage(getSize().width,
                                     getSize().height);
       fOffScreenGraphics = fOffScreenImage.getGraphics();

       // fill the offsceen buffer with blue
       fOffScreenGraphics.setColor(Color.blue);
       fOffScreenGraphics.fillRect(0, 0,
                      getSize().width, getSize().height);

       //load in the images
       for (int i=1; i<=30; i++)
       {
          fEarth[i-1] = getImage (getCodeBase(),
                                  “./Earth”+i+”.gif”);
          fTracker.addImage(fEarth[i-1], 0);
       }

       //How many milliseconds between frames?
       theString = getParameter(“fps”);
       try {
         if (theString != null) {
             theFramesPerSecond = Integer.parseInt(theString );
         }
       } catch (NumberFormatException e) {}
       fDelay = (theFramesPerSecond > 0) ?
                (1000 / theFramesPerSecond) : 100;
     }

     public void start() {
       // start a new thread for the animation
       if (fThread == null) {
           fThread = new Thread(this);
       }
       fThread.start();
     }

     public void stop() {
       // stop the animation thread
       fThread = null;
     }

     public void run() {
       // run at a low priority; animation is second-place to content
       Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
       long theStartTime = System.currentTimeMillis();

       //Here comes the show.
       try {
        fTracker.waitForID(0);
       } catch (InterruptedException e) {
         System.err.println(“Interrupted Exception: “ + e.getMessage());
         e.printStackTrace();
         return;
       }
       while (Thread.currentThread() == fThread) {

         //Advance the frame.
         fFrame++;

         //Display it.
         repaint();

         //Delay depending on how far we are behind.
         try {
              theStartTime += fDelay;
              Thread.sleep(Math.max(0,
                                    theStartTime-
                           System.currentTimeMillis()));
         } catch (InterruptedException e) {
                  break;
         }
     }
   }

   public void update( Graphics g) {

       // fill the offsceen buffer with blue
       fOffScreenGraphics.setColor(Color.blue);
       fOffScreenGraphics.clearRect(0, 0,
                      getSize().width, getSize().height);
       fOffScreenGraphics.fillRect(0, 0,
                      getSize().width, getSize().height);
       paint(g);
   }

   //Draw the current frame
   public void paint(Graphics g) {
     if (fTracker.checkID( 0 )) {
       fOffScreenGraphics.drawImage(fEarth[fFrame % 30], 0, 0, this);
       g.drawImage(fOffScreenImage, 0, 0, this);
     }
   }
 }

Using the 2D API

From its earliest days, Java has included a nice graphics class called java.awt.Graphics. To graphics professionals, however, Graphics left some features to be desired. More mature GUI platforms, such as Windows 95 and the Macintosh, support features that are not present in Graphics.

Now, in JDK 1.2, all that has changed. Sun has provided a much richer, two-dimensional graphics class called java.awt.Graphics2D. This section describes the major improvements available in Graphics2D. Listing 39.18 shows a demonstration program, PathsFill.java, that shows how to display shapes by using Graphics2D. The PathsFill class is a type of Canvas, so Graphics2D is able to draw on it by casting the Graphics parameter to paint() as a Graphics2D. The class also contains a main() method, enabling us to run it from the command line. Compile PathsFill.java by typing

javac PathsFill.java

and run it by typing

java PathsFill


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.