Полезная информация

Exploring Java

Previous: 17.2 Implementing an ImageObserverChapter 17
Working with Images
Next: 17.4 Producing Image Data
 

17.3 Using a MediaTracker

java.awt.MediaTracker is a utility class that simplifies life if we have to wait for one or more images to be loaded before they're displayed. A MediaTracker monitors the preparation of an image or a group of images and lets us check on them periodically, or wait until they are completed. MediaTracker uses the ImageObserver interface internally to receive image updates.

The following applet, LoadMe, uses a MediaTracker to wait while an image is prepared. It shows a "Loading..." message while it's waiting. (If you are retrieving the image from a local disk or very fast network, this message might go by quickly, so pay attention.)

import java.awt.*;
public class TrackImage extends java.applet.Applet implements Runnable { 
    Image img;
    final int MAIN_IMAGE = 0;
    MediaTracker tracker;
    boolean show = false;
    Thread runme;
    String message = "Loading...";
    public void init() {
        img = getImage( getClass().getResource(getParameter("img")) );
        tracker = new MediaTracker(this);
        tracker.addImage( img, MAIN_IMAGE );
    }
    public void start() {
        if ( !tracker.checkID( MAIN_IMAGE ) ) {
            runme = new Thread( this );
            runme.start();
        }
    }
    public void stop() {
        runme.stop();
        runme = null;
    }
    public void run() {
        repaint();
        try {
            tracker.waitForID( MAIN_IMAGE );
        } catch( InterruptedException e) { }
        if ( tracker.isErrorID( MAIN_IMAGE ) )
            message= "Error";
        else
            show = true;
        repaint();
    }
    public void paint( Graphics g ) {
        if ( show )
            g.drawImage( img, 0, 0, this );
        else {
            g.drawRect( 0, 0, getSize().width-1, getSize().height-1);
            g.drawString( message, 20, 20 );
        }
    }
}

From its init() method, LoadMe requests its image and creates a MediaTracker to manage it. Later, after the applet is started, LoadMe fires up a thread to wait while the image is loaded. Note that we don't do this in init() because it would be rude to do anything time-consuming there; it would take up time in an AWT thread that we don't own. In this case, waiting in init() would be especially bad because paint() would never get called and our "loading" message wouldn't be displayed; the applet would just hang until the image loaded. It's often better to create a new thread for initialization and display a startup message in the interim.

When we construct a MediaTracker, we give it a reference to our component (this). After creating a MediaTracker, we assign it images to manage. Each image is associated with an integer identifier we'll use later for checking on its status. Multiple images can be associated with the same identifier, letting us manage them as a group. The value of the identifier is also used to prioritize loading when waiting on multiple sets of images; lower IDs have higher priority. In this case, we want to manage only a single image, so we created one identifier called MAIN_IMAGE and passed it as the ID for our image in the call to addImage().

In our applet's start() method, we call the MediaTracker's checkID() routine with the ID of the image to see if it's already been loaded. If it hasn't, the applet fires up a new thread to fetch it. The thread executes the run() method, which simply calls the MediaTracker waitforID() routine and blocks on the image, waiting for it to finish loading. The show flag tells paint() whether to display our status message or the actual image. We do a repaint() immediately upon entering run() to display the "Loading..." status, and again upon exiting to change the display. We test for errors during image preparation with isErrorID() and change the status message if we find one.

This may seem like a lot of work to go through, just to put up a status message while loading a single image. MediaTracker is more valuable when we are working with many images that have to be available before we can begin parts of our application. It saves us from implementing a custom ImageObserver for every application. In the future, MediaTracker should also be able to track the status of audio clips and other kinds of media (as its name suggests).


Previous: 17.2 Implementing an ImageObserverExploring JavaNext: 17.4 Producing Image Data
17.2 Implementing an ImageObserverBook Index17.4 Producing Image Data

Other Books in this LibraryJava in a NutshellJava Language ReferenceJava AWTJava Fundamental ClassesExploring Java