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.
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>
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; } } }