Images and Sounds

Example 6.5 shows a Java applet that implements a simple client-side imagemap, which has the capability to highlight the "hot spots" in the image and play a sound clip when the user clicks on the image. Figure 6.4 shows what this applet might look like, when configured with an appropriate image.

Figure 6.4: An imagemap applet

[Graphic: Figure 6-4]

This applet demonstrates quite a few important applet techniques:

The following HTML fragment shows an example of the properties read by this applet:

<APPLET code="Soundmap.class" width=288 height=288>
<PARAM name="image" value="image.gif">
<PARAM name="sound" value="sound.au">
<PARAM name="rect0" value="114,95,151,33,#part1">
<PARAM name="rect1" value="114,128,151,33,#part2">
<PARAM name="rect2" value="114,161,151,33,#part3">
<PARAM name="rect3" value="114,194,151,33,#part4">
<PARAM name="rect4" value="114,227,151,33,#part5">
</APPLET> 

Example 6.5: An Imagemap Applet

import java.applet.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.util.*; /** * A Java applet that simulates a client-side imagemap. * Plays a sound whenever the user clicks on one of the hyperlinks. */ public class Soundmap extends Applet {
 protected Image image; // The image to display. protected Vector rects; // A list of rectangles in it. protected AudioClip sound; // A sound to play on user clicks in a rectangle. /** Initialize the applet. */ public void init() {
 // Look up the name of the image, relative to a base URL, and load it. // Note the use of three Applet methods in this one line. image = this.getImage(this.getDocumentBase(), this.getParameter("image")); // Lookup and parse a list of rectangular areas and the URLs they map to. // The convenience routine getRectangleParameter() is defined below. rects = new Vector(); ImagemapRectangle r; for(int i = 0; (r = getRectangleParameter("rect" + i)) != null; i++) rects.addElement(r); // Look up a sound to play when the user clicks one of those areas. sound = this.getAudioClip(this.getDocumentBase(), this.getParameter("sound")); // Specify an "event listener" object to respond to mouse button // presses and releases. Note that this is the Java 1.1 event model. // Note that it also uses a Java 1.1 inner class, defined below. this.addMouseListener(new Listener());
}
/** Called when the applet is being unloaded from the system. * We use it here to "flush" the image we no longer need. This may * result in memory and other resources being freed more quickly. */ public void destroy() {
 image.flush();
}
/** To display the applet, we simply draw the image. */ public void paint(Graphics g) {
 g.drawImage(image, 0, 0, this);
}
/** We override this method so that it doesn't clear the background * before calling paint(). No clear is necessary, since paint() overwrites * everything with an image. Causes less flickering this way. */ public void update(Graphics g) {
 paint(g);
}
/** Parse a comma-separated list of rectangle coordinates and a URL. * Used to read the imagemap rectangle definitions from applet parameters. */ protected ImagemapRectangle getRectangleParameter(String name) {
 int x, y, w, h; URL url; String value = this.getParameter(name); if (value == null) return null; try {
 StringTokenizer st = new StringTokenizer(value, ","); x = Integer.parseInt(st.nextToken()); y = Integer.parseInt(st.nextToken()); w = Integer.parseInt(st.nextToken()); h = Integer.parseInt(st.nextToken()); url = new URL(this.getDocumentBase(), st.nextToken());
}
catch (NoSuchElementException e) {
 return null;
}
catch (NumberFormatException e) {
 return null;
}
catch (MalformedURLException e) {
 return null;
}
return new ImagemapRectangle(x, y, w, h, url);
}
/** * An instance of this inner class is used to respond to mouse events. */ class Listener extends MouseAdapter {
 /** The rectangle that the mouse was pressed in. */ private ImagemapRectangle lastrect; /** Called when a mouse button is pressed. */ public void mousePressed(MouseEvent e) {
 // On button down, check if we're inside one of the specified rectangles. // If so, highlight the rectangle, display a message, and play a sound. // The utility routine findrect() is defined below. ImagemapRectangle r = findrect(e); if (r == null) return; Graphics g = Applet.this.getGraphics(); g.setXORMode(Color.red); g.drawRect(r.x, r.y, r.width, r.height); // highlight rectangle Applet.this.showStatus("To: " + r.url); // display URL sound.play(); // play the sound lastrect = r; // Remember the rectangle so it can be un-highlighted.
}
/** Called when a mouse button is released. */ public void mouseReleased(MouseEvent e) {
 // When the button is released, un-highlight the rectangle. If the // mouse is still inside it, ask the browser to go to the URL. if (lastrect != null) {
 Graphics g = Applet.this.getGraphics(); g.setXORMode(Color.red); g.drawRect(lastrect.x, lastrect.y, lastrect.width, lastrect.height); Applet.this.showStatus(""); // Clear the message. ImagemapRectangle r = findrect(e); if ((r != null) && (r == lastrect)) // If still in the same rectangle Applet.this.getAppletContext().showDocument(r.url); // Go to the URL lastrect = null;
}
} /** Find the rectangle we're inside. */ protected ImagemapRectangle findrect(MouseEvent e) {
 int i, x = e.getX(), y = e.getY(); for(i = 0; i < rects.size(); i++) {
 ImagemapRectangle r = (ImagemapRectangle) rects.elementAt(i); if (r.contains(x, y)) return r;
}
return null;
}
} /** * A helper class. Just like java.awt.Rectangle, but with a URL field. * Note the use of a nested top-level class for neatness. */ static class ImagemapRectangle extends Rectangle {
 URL url;
public ImagemapRectangle(int x, int y, int w, int h, URL url) {
 super(x, y, w, h); this.url = url;
}
}
}