Wednesday, October 12, 2011

Load Faster Images in Applets

When loading images over a network, a common problem which Java applets face is images not loading properly. On a fast network connection the image will load quickly, but over a slow modem or network connection, images take longer, or may not arrive at all. Users may be confused by blank images - particularly when a sequence of images are being displayed. One simple way to let your users know you're still loading is to use MediaTracker, which allows applets to detect when images are loaded. 
Ask any user who is connected via a modem dial-up connection, what they think about applets, and the answer is frequently that they are slow to load. As one user puts it, "I hate the ugly gray applet box that sits there on the page". Quite often, an applet is loading images for some form of animation - but the user doesn't know what is going on. Other times, applets that fail to load properly just sit there with a blank gray box. This adds to the confusion, because a slow loading applet is often equated with a broken one.
When writing applets, we as programmers have a responsibility to users to let them know what's going on. If your applet loads images over a network connection, it's important to track their progress, and notify the user. 
"I hate the ugly gray applet box that sits there on the page.

That's where MediaTracker comes in. MediaTracker allows applets to check to see whether an image has loaded or not. Applets can register images with a MediaTracker object, and then wait until one or all images have loaded. While the images are loading, a message can be displayed to the user. When all the images are loaded, they can then be processed by the applet - for example, displayed as part of an animation. Note though MediaTracker can benefit applications, as well as applets - even when loading from a local file-system, there can be a noticeable delay when many large images are loaded.
MediaTracker is a class in the AWT package. If you're already working with images, the AWT package will be imported. If not, you'll need to add the following lines to the beginning of your code :-
// Import the AWT graphics package
import java.awt.*;
Next, you need to create an instance of java.awt.MediaTracker. You must pass an instance of java.awt.Component to MediaTracker's constructor. An applet is a subclass of Component, so when writing an applet for a web-page, the applet can pass itself by using the this keyword.
// Create a MediaTracker instance,
// to montior loading of images
tracker = new MediaTracker(this);
Once you have a MediaTracker, simply load each image and register it, using the MediaTracker.addImage (Image, int) method. It takes as its first parameter an image, and the idcode of the image as its second parameter. The idcode can be used to inquire about the status of a particular image, rather than a group of images.
// Load the image
Image img = getImage( getDocumentBase(),
                     "picture.jpg" ); 

// Register it with media tracker
tracker.addImage(img, 1);
Once you've registered the image, you can display a text message, or a simple animation, to let your users know that data is loading. Of course, you'll also have to check to see if the images are ready for use, by querying MediaTracker.
There are two ways to check on the progress of images. The first is to continually poll MediaTracker, by using the MediaTracker.checkID(int) method.
// Check to see if it has loaded
if (tracker.checkID(1) == false)
{
 // Not yet, display message .....
}
else
{
 // Display the animation
}
Another way, and often the simpler, is to just wait indefinitely, until all images are loaded. Note that it's best to do this in a separate thread of execution, so that your applet can continue to respond to user events and display a message. This is a blocking operation, whereas the MediaTracker.checkID(int) method is non-blocking and returns immediately.
// Wait until all images have loaded
tracker.waitForAll();

No comments: