- Special Edition Using Java, 2nd Edition -

Chapter 16

Advanced Applet Code


by Clayton Walnum

Now that you can create simple applets, it's time to dig in a little deeper and learn the secrets that separate the Java applet programmers from the boys (or the girls, as the case may be). After you've finished this chapter, you'll be able to write just about any type of applet you like.

The Four Stages of an Applet's Life Cycle

Every Java applet you create inherits a set of default behaviors from the Applet class. In most cases, these default behaviors do nothing, unless you override some of Applet's methods in order to extend the applet's basic functionality. However, although a simple applet might not seem to do much, a lot is going on in the background. Some of this activity is important to your understanding of applets, and some of it can stay out of sight and out of mind.

Part of what goes on in a simple applet is the execution of the applet's life cycle. There are four parts to this cycle, each of which has a matching method that you can override to gain access to that cycle of the applet's life. The four stages of an applet's life cycle are listed here:

Although it's not official, I like to think that there is a paint stage between the stop and start stages. This "paint stage" occurs whenever the applet's display must be drawn on the screen. This happens right after the applet's start stage, as well as whenever the applet's display must be restored or changed. This can happen when the applet is exposed from underneath another window or when the program changes the applet's display in some way and explicitly repaints the applet. Every applet you write will have a paint() method, which is the method you override to provide your applet with its display. Truth is, the paint() method isn't even defined in the Applet class. Rather, Applet inherits paint() from the Component class, a superclass in Applet's long chain of inheritance, which goes from Applet to Panel to Container and finally to Component.
 

Overriding the Life Cycle Methods

All this talk about life cycles and overriding methods may have left you a little confused as to how all this actually applies to the applets you want to create. In the previous chapter, you managed to create applets without dealing with most of this stuff because the Applet class, from which you derived your own applet classes, handled the life-cycle methods in the default manner proscribed by the Java system. If you look at listing 16.1, you see a small applet that overrides all the methods (including paint()) needed to provide custom behaviors for all the applet's life-cycle stages.

Listing 16.1 MyApplet2.java: Overriding the applet life-cycle methods.

import java.applet.*;
import java.awt.*;
public class MyApplet2 extends Applet
{
public void init()
{
// Place initialization cycle code here.
}
public void start()
{
// Place start cycle code here.
}
public void paint(Graphics g)
{
// Place paint cycle code here.
}
public void stop()
{
// Place stop cycle code here.
}
public void destroy()
{
// Place destroy cycle code here.
}
}

Notice that in order to override the paint() method, you must import the java.awt.* libraries, which contain information about the Graphics class. As you learned when writing previous applets in this book, the Graphics class enables you to display information and graphics in an applet's display area (or canvas, as the display area is sometimes called).

If you look for the previous methods in Java's source code, you'll discover that the default implementations of init(), start(), paint(), stop(), and destroy() do nothing at all. If you want your applet to do something in response to these cycles, you have to provide the code yourself by overriding the appropriate method.

Configurable Applets

All of the applets you've written so far have one thing in common. Outside of the starting size of the applet, none of your applets are configurable. That is, the user can't configure the applet to fit his needs. In many cases, it doesn't make sense to give the user configurable options. But, just as often, someone who wants to use your applet in his own home page will want to make minor changes without having to change and recompile the source code. In fact, the user probably won't even have access to the source code. In this section, you get a look at configurable applets, which enable the applet's user to modify how an applet looks and acts, all without having to change a line of Java code.

Types of Users

Before you read further, it might be a good idea to define exactly what a "user" is. When it comes to applets, you could say that there are two kinds of users. The first kind is a net surfer who logs onto your home page and sees all the cool applets you've spent the last six months creating. Because this user is not installing your applets on her own Web pages—she's just a casual observer—she doesn't need access to the applet's parameters. In fact, if you want your Web pages to look right for different users, it just doesn't make sense to enable the surfer to configure an applet.

The other kind of user is the guy who found your applet on a server somewhere and wants to incorporate the applet into his own Web pages. Assuming that you've released your applet into the world for others to use, you want this type of user to find your applet to be as flexible as possible. However, you probably don't want to give this user your source code and expect him to make changes that require recompiling. Hey, he could end up trashing the applet completely, right?

So, to make it easy for this user to modify the applet's appearance and functionality, you must build in support for parameters. To use these parameters, the user only needs to add a few lines to the HTML document that loads and runs the applet. For example, you may have written an applet that displays an awesome title on your home page. Now, you want to release the applet so that other netfolks can use it in their Web pages. However, these folks are going to want to display their own title. So, you make the title string a parameter.

In the sections that follow, you learn not only how to support applet parameters, but also how to make those parameters idiot-proof.

Parameters and Applets

When you want to use an applet that supports parameters, you must add the parameters and their values to the HTML document that loads and runs the applet. You do this using the <PARAM> tag, which has two parts:

For example, suppose you want to provide a title parameter for that title applet you read about in the previous section. The parameter tag might look like this:

<PARAM NAME=title VALUE="Big Al's Home Page">

Here, the name of the parameter is title. The applet uses this name to identify the parameter. The value of the title parameter in the previous line is the text string Big Al's Home Page. The applet retrieves this text string in order to display the title that the user wants. A complete HTML document for the title applet might look something like listing 16.2.

Listing 16.2 LST16_02.TXT: Using a parameter in an HTML document.

<title>Applet Test Page</title>
<h1>Applet Test Page</h1>
<applet
code="TitleApplet.class"
width=250
height=150
name="TitleApplet">
<PARAM NAME=title VALUE="Big Al's Home Page">
</applet>

As you can see, the <PARAM> tag is enclosed between the <applet> and </applet> tags. that is, the parameters are part of the applet's HTML code.

How does your applet retrieve the parameter at run time? To retrieve a parameter, you call the applet's getParameter() method, like this:

String param = getParameter(name);

The getParameter() method takes a single argument, which is a string containing the name of the parameter for which you want the value. The method always returns a string to your applet. This string is, of course, the part of the <PARAM> tag that follows the VALUE=.

Suppose that you've written an applet that displays a fancy greeting to the viewer. (How fancy the greeting is depends upon the code you've written for the applet. But, how the applet actually displays this greeting is not important at this point, so just pretend it does something really cool.) The parameter is defined in the HTML document like this:

<PARAM NAME=greeting VALUE="All Web Surfers Welcome!">

When the applet runs, it has to find out what greeting to display. So, in the applet's init() method is the following line:

String str = getParameter("greeting");

Now that the applet has the text stored in the str variable, it can manipulate and display it any way it needs to.

Using a Parameter in an Applet

Now that you know how to create HTML documents that set parameters, as well as how to obtain those parameters from within your applet, you'd probably like a real parameterized applet with which you can experiment. Listing 16.3 is an applet called ConfigApplet, which takes a single parameter. This parameter is the text string that the applet should display. Listing 16.4 is the HTML document that loads and runs the applet. Notice the <PARAM> tag. When you run the applet with Appletviewer, you see the window shown in figure 16.1.

Listing 16.3 ConfigApplet.java: An applet with a single parameter.

import java.awt.*;
import java.applet.*;
public class ConfigApplet extends Applet
{
String str;
public void init()
{
str = getParameter("text");
Font font = new Font("TimesRoman", Font.BOLD, 24);
setFont(font);
}
public void paint(Graphics g)
{
g.drawString(str, 50, 50);
}
}

Listing 16.4 CONFIGAPPLET.HTML: ConfigApplet's HTML document.

<title>Applet Test Page</title>
<h1>Applet Test Page</h1>
<applet
code="ConfigApplet.class"
width=250
height=150
name="ConfigApplet">
<PARAM NAME=text VALUE="Display Text">
</applet>

FIG. 16.1

This applet's display string is given as a parameter.

Once you get ConfigApplet compiled, try running the applet several times, each time changing the parameter in the HTML document to a new text string. This gives you a good example of how parameters work from the HTML document writer's point of view. Changing the value of the parameter in the HTML document is all you need to do to display a different text string. You don't have to change the applet's source code at all.

Multiple Parameters

When you're writing an application that others may use in their Web pages, it's important that you make the applet as flexible as possible. One way to do this is to use parameters for any applet value that the user might like to customize. Adding multiple parameters is just a matter of adding additional <PARAM> tags to the HTML document and then retrieving the values of the parameters in the applet. In the next example, you take a look at ConfigApplet2, which gives the user much more control over how the applet displays the text string.

Suppose that you want to rewrite ConfigApplet so that the user can customize not just the text string that the applet displays, but also the position of the text and the size of the font used to print the text. To do this, you need to create four parameters, one each for the text to display, the X position of the text, the Y position of the text, and the point size of the font. Listing 16.5 is an HTML document that loads and runs the ConfigApplet2 applet, which is a new version of ConfigApplet. Notice that the HTML document now specifies four parameters for the applet. You can specify as many parameters as you need, in any order, for an applet.

Listing 16.5 CONFIGAPPLET2.HTML: HTML document for ConfigApplet2.

<title>Applet Test Page</title>
<h1>Applet Test Page</h1>
<applet
code="ConfigApplet2.class"
width=350
height=200
name="ConfigApplet2">
<PARAM NAME=text VALUE="Display Text">
<PARAM NAME=typesize VALUE=72>
<PARAM NAME=xpos VALUE=20>
<PARAM NAME=ypos VALUE=100>
</applet>

In this HTML document, the user is specifying that he wants to display the text string Display Text in 72-point type and at position 20,100. The applet, of course, must call getParameter() to read these values into the applet. Moreover, the applet must call getParameter() once for each parameter. After retrieving the parameters, the applet must initialize itself such that it displays the text as requested. Listing 16.6 is the Java source code for ConfigApplet2, which accomplishes all of these tasks. Figure 16.2 shows the applet running under Appletviewer, using the parameters given in the HTML document in listing 16.5.

Because the getParameter() method always returns a string, you may have to convert some parameters before you can use them in your applet. For example, the ConfigApplet2 applet must convert its typesize, xpos, and ypos parameters from strings to integers.
 

Listing 16.6 ConfigApplet2.java: The ConfigApplet2 applet.

import java.awt.*;
import java.applet.*;
public class ConfigApplet2 extends Applet
{
String str;
Point position;
public void init()
{
String s;
str = getParameter("text");
s = getParameter("typesize");
int typeSize = Integer.parseInt(s);
s = getParameter("xpos");
int xpos = Integer.parseInt(s);
s = getParameter("ypos");
int ypos = Integer.parseInt(s);
position = new Point(xpos, ypos);
Font font = new Font("TimesRoman", Font.BOLD, typeSize);
setFont(font);
}
public void paint(Graphics g)
{
g.drawString(str, position.x, position.y);
}
}

FIG. 16.2

This applet accepts four parameters that determine how the text is displayed.

Suppose you were to change the parameters in the HTML file to those shown in listing 16.7. You'd then completely change the way the text string is displayed in the applet, as shown in figure 16.3. As you can see, parameters can have a profound effect on the way an applet looks and acts.

Listing 16.7 LST16_07.TXT: New parameters for ConfigApplet2.

<PARAM NAME=text VALUE="New Text String">
<PARAM NAME=typesize VALUE=18>
<PARAM NAME=xpos VALUE=60>
<PARAM NAME=ypos VALUE=150>

FIG. 16.3

Here's ConfigApplet2 running with different parameters.

Default Parameter Values

You might have noticed by now that there's a big problem with the ConfigApplet and ConfigApplet2 applets. Neither applet checks to ensure that the parameters it tries to retrieve exist. For example, what happens when the user forgets to include the text parameter?

Relying on other people to provide your applet with the data it needs is a dangerous practice. Your applet should always check the validity of values returned from the getParameter() method. At the very least, you should be sure that the returned value is not null, which is the value getParameter() returns when a particular parameter doesn't exist (that is, the user forget to define it in the HTML document or deliberately left it out assuming that the applet will automatically use a default value for the missing one).

To ensure that your applet is in a runnable state after retrieving parameters, you must always check the parameter's values and supply default values for those parameters that are missing or invalid. For example, to make sure that your applet has a text string to display, you might use lines like this:

str = getParameter("text");
if (str == null)
str = "Default Text";

If you decide to release your applets so other people can use them in their Web pages, be sure that you include a separate documentation file that describes the applet's parameters and shows how to use them. Also, you should support the getAppletInfo() and getParameterInfo() method in your applet, which is described in this chapter's section entitled "The java.applet Package."
 

You can now extend the ConfigApplet2 so that it provides default values for each parameter. When you've done this, the applet can run without generating errors no matter what parameters the user chooses to include or ignore. Listing 16.8 is the new version, called ConfigApplet3.

Notice that although the program now checks for missing parameters, it doesn't limit the values to any ranges or otherwise check their validity. Because the text parameter is always a string, there's really nothing you need to check for (except null). However, you may want to limit the font size or make sure that the display location is inside the applet's window. Listing 16.9 is the HTML document used to load and run the applet as it's displayed in figure 16.4.

Listing 16.8 ConfigApplet3.java: This applet provides default values for all parameters.

import java.awt.*;
import java.applet.*;
public class ConfigApplet3 extends Applet
{
String str;
Point position;
public void init()
{
HandleTextParam();
HandleTypeSizeParam();
HandlePositionParam();
}
public void paint(Graphics g)
{
g.drawString(str, position.x, position.y);
}
protected void HandleTextParam()
{
str = getParameter("text");
if (str == null)
str = "Default Text";
}
protected void HandleTypeSizeParam()
{
String s = getParameter("typesize");
if (s == null)
s = "24";
int typeSize = Integer.parseInt(s);
Font font = new Font("TimesRoman", Font.BOLD, typeSize);
setFont(font);
}
protected void HandlePositionParam()
{
String s = getParameter("xpos");
if (s == null)
s = "20";
int xpos = Integer.parseInt(s);
s = getParameter("ypos");
if (s == null)
s = "50";
int ypos = Integer.parseInt(s);
position = new Point(xpos, ypos);
}
}

Listing 16.9 CONFIGAPPLET3.HTML: The HTML document for ConfigApplet3.

<title>Applet Test Page</title>
<h1>Applet Test Page</h1>
<applet
code="ConfigApplet3.class"
width=630
height=200
name="ConfigApplet3">
<PARAM NAME=text VALUE="Hi there!">
<PARAM NAME=typesize VALUE=144>
<PARAM NAME=xpos VALUE=40>
<PARAM NAME=ypos VALUE=140>
</applet>

FIG. 16.4

This is ConfigApplet3 running under Appletviewer.

Images

If you've seen the applets that are floating around, you've undoubtedly noticed that many feature vivid graphics and even sound effects. When programming in a language such a C++, displaying graphics and playing sounds can be notoriously difficult, thanks to the fact that these languages provide no direct support for handling these types of files. Even the Windows API, as immense as it is, provides little help when it comes to dealing with these graphical and aural chores. Java, on the other hand, was designed to make creating applets as easy as possible. For that reason, Java's classes handle almost all the difficulties associated with displaying images (commonly called bitmaps) and playing sounds. In this section, you use Java's power to add images to your applets. Later in this chapter, you learn about sounds.

Image Types

In the world of computers, there are many types of images, each of which is associated with a specific file format. These image types are usually identified by their file extensions, which include PCX, BMP, GIF, JPEG (or gif), TIFF (or TIF), TGA, and more. Each of these file types was created by third-party software companies for use with their products, but many became popular enough to grow into standards. The PCX graphics file type, for example, began as the format for PC Paintbrush files, whereas BMP files are usually associated with the Windows graphical interface.

If you were writing your Internet applications using a more conventional language like C++, you could choose to support whatever image type was most convenient for your use. This is because you'd have to write all the file-loading code from scratch, anyway. Java, on the other hand, comes complete with classes that are capable of loading image files for you. This convenience comes with a small price, however, since Java can load only GIF and JPEG image file formats. In this book, you use GIF files, which are more common, although JPEG files are rapidly gaining a reputation, especially for high-resolution, true-color images.

Understanding getDocumentBase() and getCodeBase()

The first step in displaying an image in your applet is to load the image from disk. To do this, you must create an object from Java's Image class. This is easy to do; however, you need to create a URL object that holds the location of the graphics file. You could just type the image's URL directly into your Java source code. If you do this, however, you have to change and recompile the applet whenever you move the graphics file to a different directory on your disk. A better way to create the image's URL object is to call either the getDocumentBase() or getCodeBase() method. The former returns the URL of the directory from which the current HTML file was loaded, whereas the latter returns the URL of the directory from which the applet was run. If you're storing your images in the same directory (or a subdirectory of that directory) as your HTML files, you'd want to use getDocumentBase() to obtain an URL for an image.

Suppose you have your HTML documents in the C:/PUBLIC directory and the image you want, called IMAGE.GIF, is stored in a subdirectory of PUBLIC called IMAGES. A call to getDocumentBase() gets you the appropriate base URL. That call looks like this:

URL url = getDocumentBase();

As you'll soon see, once you have the URL, you can load the file by using the URL along with the relative location of the image, which in this case would be IMAGES/IMAGE.GIF. The full URL to the file would then be FILE:/C:/PUBLIC/IMAGES/IMAGE.GIF. If you decided to move your public files to a directory called MYHOMEPAGE, the call to getDocumentBase() gives you the URL for that new directory, without you having to change the applet's source code. Once you include the relative location of the image file, this new URL would be FILE:/C:/MYHOMEPAGE/IMAGES/IMAGE.GIF.

The getCodeBase() method works similarly to getDocumentBase(), except that it returns the URL of the directory from which the applet was loaded. If you're storing your images in the same directory (or a subdirectory of that directory) as your .class files, you'd want to call getCodeBase() to obtain a URL for an image.

Suppose you have your .class files in the C:/CLASSES directory and the image you want (still called IMAGE.GIF) is stored in a subdirectory of CLASSES called IMAGES. A call to getCodeBase() gets you the base URL you need to load the image. That call looks like:

URL url = getCodeBase();

Again, once you have the URL, you can load the file by using the URL along with the relative location of the image, which would still be IMAGES/IMAGE.GIF. The full URL to the file would then be FILE:/C:/CLASSES/IMAGES/IMAGE.GIF.

Loading an Image

Once you have the image's base URL, you're ready to load the image and create the Image object. You can complete both of these tasks at the same time, by calling your applet's getImage() method, like this:

Image image = getImage(baseURL, relLocation);

The getImage() method's two arguments are the URL returned by your call to getCodeBase() or getDocumentBase() and the relative location of the image. For example, assuming that you've stored your .class files in the directory C:\CLASSES and your images in the directory C:\CLASSES\IMAGES, you'd have code that looks something like this:

URL codeBase = getCodeBase();
Image myImage = getImage(codeBase, "images/myimage.gif");

After Java has executed the above lines, your image is loaded into the computer's memory and ready to display.

Displaying an Image

Displaying the image is a simple matter of calling the Graphics object's drawImage() method, like this:

g.drawImage(myImage, x, y, width, height, this);

This method's arguments are the image object to display, the X and Y coordinates at which to display the image, the width and height of the image, and the applet's this reference.

When you want to display an image with its normal width and height, you can call a simpler version of the drawImage() method, which leaves out the width and height arguments, like this: drawImage(image, x, y, this). This version of the method actually draws the image faster because it doesn't have to worry about reducing or expanding the image to the given width and height. It just blasts it on to the screen exactly as the image normally appears.
 

You may be wondering where you can get the width and the height of the image. As it turns out (no doubt thanks to careful consideration by Java's programmers over hundreds of cups of coffee), the Image class has two methods, getWidth() and getHeight(), that return the width and height of the image. The complete code for displaying the image, then, might look like this:

int width = image.getWidth(this);
int height = image.getHeight(this);
g.drawImage(image, x, y, width, height, this);

As you can see, the getWidth() and getHeight() methods require a single argument, which is the applet's this reference.

Displaying an Image in an Applet

You're now ready to write an applet that can display images. Listing 16.10 is the Java source code for an applet called ImageApplet that displays a small image using the techniques described previously in this chapter. When you run the applet with Appletviewer, you see the window shown in figure 16.5. Make sure the SNAKE.GIF image is in the same directory as the ImageApplet.class file, because that's where the program expects to find it.

Listing 16.10 ImageApplet.java: An applet that displays an image.

import java.awt.*;
import java.applet.*;
import java.net.*;
public class ImageApplet extends Applet
{
Image snake;
public void init()
{
URL codeBase = getCodeBase();
snake = getImage(codeBase, "snake.gif");
resize(250, 250);
}
public void paint(Graphics g)
{
int width = snake.getWidth(this);
int height = snake.getHeight(this);
g.drawRect(52, 52, width+10, height+10);
g.drawImage(snake, 57, 57, width, height, this);
}
}

FIG. 16.5

This is ImageApplet running under Appletviewer.

Notice how the applet imports the classes in the net package, which is where the URL class lives. If you fail to include this line at the top of the program, Java will be unable to find the URL class and the applet will not compile.

By using different values for the drawImage() method's width and height arguments, you can display an image at any size you like. For example, to display an image at twice its normal size, just use 2*width and 2*height for the width and height arguments. To display the image at half its normal size, use width/2 and height/2. Figure 16.6 shows the snake image displayed at twice its normal size. It doesn't even fit in the window any more!
 


FIG. 16.6

Here's the snake image at twice its size.

Playing a Sound

Just as there are many types of image files, so too are there many types of sound files. But, when it comes to applets, the only type of sound file you need to know about are audio files, which have the file extension AU. These types of sound files were popularized on UNIX machines and are the only type of sound file Java can currently load and play.

When you want to play a sound from beginning to end, you only have to call getDocumentBase() or getCodeBase() for the URL and then call play() to play the sound. A call to play() looks like this:

play(baseURL, relLocation);

The play() method's two arguments are the URL returned from a call to getDocumentBase() or getCodeBase() and the relative location of the sound file.

Suppose you have your .class files in the directory C:/MYHOMEPAGE and your AU files in the directory C:/MYHOMEPAGE/AUDIO. The following lines then will load and play an audio file called SOUND.AU:

URL codeBase = getCodeBase();
play(codeBase, "audio/sound.au");

Playing a Sound in an Applet

Now get ready to write an applet that plays a sound file. Listing 16.11 is the applet in question, called SoundApplet. When you run the applet with Appletviewer, you see the window shown in figure 16.7. Just click the button to hear the sound. Of course, you need to have a sound card properly installed on your system. You also must be sure that the SPACEMUSIC.AU sound file is in the same directory as the applet.

Listing 16.11 SoundApplet.java: An applet that plays a sound file.

import java.awt.*;
import java.applet.*;
import java.net.*;
public class SoundApplet extends Applet
{
Button button;
public void init()
{
BorderLayout layout = new BorderLayout();
setLayout(layout);
Font font = new Font("TimesRoman", Font.BOLD, 32);
setFont(font);
button = new Button("Play Sound");
add("Center", button);
resize(250, 250);
}
public boolean action(Event evt, Object arg)
{
if (evt.target instanceof Button)
{
URL codeBase = getCodeBase();
play(codeBase, "spacemusic.au");
}
return true;
}
}

FIG. 16.7

Click the button to hear the applet's sound file.

Controlling Sounds

Although the applet's play() method is the easiest way to load and play sounds, it doesn't give you much control. You have only one option: play the sound from beginning to end. If you want a little more control over your sounds, you can create an AudioClip object and use the object's methods to control the sound. Unfortunately, even the AudioClip class doesn't give you much power, although you can play, stop, and loop the sound.

To create the AudioClip object, you call the getAudioClip() method, like this:

AudioClip audioClip = getAudioClip(baseURL, relLocation);

This method's two arguments are the sound file's base URL and relative location.

Once you have the AudioClip object created and loaded, you can call its methods to control the sound. There are only three from which to choose: play(), stop(), and loop(). The play() method plays the sound once from beginning to end, stop() stops the sound whether or not it has finished playing, and loop() causes the sound to keep repeating until it's stopped.

Using an Audio Clip in an Applet

Although using audio clips is a little more complicated than simply loading and playing a sound using the applet's play() method, it's still a straightforward process. Listing 16.12 is an applet that creates an AudioClip object and enables the user to send commands to the object using the applet's command buttons. When you run the applet with Appletviewer, you see the window shown in figure 16.8. To play the sound once from beginning to end, click the Play button. To stop the sound at any time, click the Stop button. Finally, to play the sound over and over, click the Loop button.

Listing 16.12 SoundApplet2.java: An Applet that creates and plays an AudioClip object.

import java.awt.*;
import java.applet.*;
import java.net.*;
public class SoundApplet2 extends Applet
{
AudioClip soundClip;
public void init()
{
GridLayout layout = new GridLayout(1, 3, 10, 10);
setLayout(layout);
Font font = new Font("TimesRoman", Font.BOLD, 24);
setFont(font);
Button button = new Button("Play");
add(button);
button = new Button("Stop");
add(button);
button = new Button("Loop");
add(button);
URL codeBase = getCodeBase();
soundClip = getAudioClip(codeBase, "spacemusic.au");
resize(250, 250);
}
public boolean action(Event evt, Object arg)
{
if (arg == "Play")
soundClip.play();
else if (arg == "Stop")
soundClip.stop();
else if (arg == "Loop")
soundClip.loop();
return true;
}
}

FIG. 16.8

This is Appletviewer running SoundApplet2.

Events

Although events are covered in detail in Chapter 20, "Exceptions and Events in Depth," you get an introduction to them here. In the previous chapter, you discovered that many of Java's components such as buttons trigger events that you can handle in an applet's action() method. You also learned that events generated by the user's mouse can be responded to in an applet's mouseDown() and mouseMove() methods. There are, however, many event-handling methods you haven't seen yet.

For example, other mouse methods you can include in your applet are mouseEnter() (which Java calls when the mouse pointer enters the applet), mouseExit() (which Java calls when the mouse pointer leaves the applet), and mouseDrag() (which Java calls when the user moves the mouse pointer with the left mouse button pressed. For example, listing 16.13 is an applet that displays the message Mouse entered when the mouse pointer enters the applet and displays the message "Mouse exited" when the mouse pointer exits the applet. Figure 16.9 shows the applet running under Appletviewer.

Listing 16.13 MouseApplet.java: Using the mouseEnter() and mouseExit() methods.

import java.awt.*;
import java.applet.*;
public class MouseApplet extends Applet
{
String msgStr;
public void init()
{
msgStr = "";
Font font =
new Font("TimesRoman", Font.BOLD, 48);
setFont(font);
resize(400, 300);
}
public void paint(Graphics g)
{
g.drawString(msgStr, 40, 120);
}
public boolean mouseEnter(Event evt, int x, int y)
{
msgStr = "Mouse entered";
repaint();
return true;
}
public boolean mouseExit(Event evt, int x, int y)
{
msgStr = "Mouse exited";
repaint();
return true;
}
}

FIG. 16.9

Your applet can track the mouse's entering or exiting the applet.

You can handle keyboard events by writing keyDown() or keyUp() methods for your applet. Java calls keyDown() whenever the user types a key on his keyboard and calls keyDown() when the user releases the key. Both of these methods receive the key pressed or released as an argument. Listing 16.14 is an applet that displays whatever key the user presses. Figure 16.10 shows Appletviewer running the applet.

Listing 16.14 KeyApplet.java: Responding to key presses.

import java.awt.*;
import java.applet.*;
public class KeyApplet extends Applet
{
int keyPressed;
public void init()
{
keyPressed = -1;
Font font =
new Font("TimesRoman", Font.BOLD, 144);
setFont(font);
resize(200, 200);
}
public void paint(Graphics g)
{
String str = "";
if (keyPressed != -1)
{
str += (char)keyPressed;
g.drawString(str, 40, 150);
}
}
public boolean keyDown(Event evt, int key)
{
keyPressed = key;
repaint();
return true;
}
}

FIG. 16.10

Java's events also enable an applet to capture key presses.

The remaining event-handling methods—gotFocus() and lostFocus()—enable your applet (or other component) to determine when it has received or lost the focus. When the user selects the applet (usually by clicking it), Java calls gotFocus() in order to notify the applet that it is now the window that will receive user input. When the user selects another window, Java calls the applet's lostFocus() method in order to notify the applet that it is no longer the active window. Listing 16.15 is an applet that demonstrates how the gotFocus() and lostFocus() methods work. When the applet is the active window, the applet displays the message "Got focus" (see fig. 16.11). When you switch away from the applet, the applet displays the message "Lost focus" (see fig. 16.12).

Event-handling methods such as mouseEnter(), mouseExit(), gotFocus(), and lostFocus() are actually methods of the Component class (from which Applet inherits much of it functionality), which means any Java component is capable of receiving and handling the associated events.
 

Listing 16.15 FocusApplet.java: An applet that knows its focus state.

import java.awt.*;
import java.applet.*;
public class FocusApplet extends Applet
{
String msgStr;
public void init()
{
msgStr = "";
Font font =
new Font("TimesRoman", Font.BOLD, 48);
setFont(font);
resize(400, 300);
}
public void paint(Graphics g)
{
g.drawString(msgStr, 40, 120);
}
public boolean gotFocus(Event evt, Object arg)
{
msgStr = "Got focus";
repaint();
return true;
}
public boolean lostFocus(Event evt, Object arg)
{
msgStr = "Lost focus";
repaint();
return true;
}
}

FIG. 16.11

When FocusApplet receives the input focus, it displays this message.


FIG. 16.12

This is FocusApplet after it has lost its focus to WordPad.

The java.applet Package

All of an applet's basic functionality can be found in the java.applet package or in the classes from which the java.applet classes are derived. The most important of these classes is, of course, the Applet class itself, which can trace its ancestry from Applet to Component to Container and finally to Panel. The Panel, Container, and Component classes are defined as part of the awt package and are covered in detail in Chapter 31, "java.awt." In this section, you do, however, get a brief look at some of the methods contained in these classes, because many are important to applet development.

The java.applet package contains the Applet and AudioClip classes. In addition, you find that the AppletContext and AppletStub interfaces are located here. The AppletContext and AppletStub interfaces are, for the most part, used internally by Java, so you probably never have to deal with it directly. You already know everything about AudioClip, thanks to the section "Images and Sounds" earlier in this chapter. That leaves you with the Applet class to explore, much of which you've already used in previous applets. Table 16.1 lists the methods of the Applet class that are most useful to you as an applet programmer.

Table 16.1 Useful Methods of the Applet Class

Method Description
destroy() Destroys the applet. The fourth of the four life-cycle methods.
getAppletContext() Gets the applet's applet context, which usually represents the browser in which the applet is running.
getAppletInfo() Gets a string containing information about the applet.
getAudioClip() Gets a reference to an audio clip object.
getCodeBase() Gets the URL from which the applet was run.
getDocumentBase() Gets the URL from which the applet's HTML document was loaded.
getImage() Gets a reference to an image object.
getParameter() Gets an applet parameter.
getParameterInfo() Gets a string array containing parameter information.
init() Initializes the applet. The first of the four life-cycle methods.
isActive() Returns true if the applet is active.
play() Plays an audio clip.
resize() Sizes an applet.
showStatus() Displays a message in the applet context (usually a browser).
start() Starts the applet. The second of the four life-cycle methods.
stop() Stops the applet. The third of the four life-cycle methods.

You've already had experience with all of the methods in table 16.1 except getAppletInfo(), getParameterInfo(), isActive(), and showStatus(). There's nothing to using isActive(); you just call it when you want to know whether the applet is currently active. A return value of true means that the applet is active and false means that it's not active.

The showStatus() method simply displays a text message in the status bar of the browser (the applet context) in which the applet is running. Listing 16.16 , for example, shows a new version of FocusApplet, called StatusApplet, that displays a message in the browser's status bar whenever the applet gains or loses the focus.

Listing 16.16 StatusApplet.java: Displaying a message in the browser's status bar.

import java.awt.*;
import java.applet.*;
public class StatusApplet extends Applet
{
public boolean gotFocus(Event evt, Object arg)
{
showStatus("Got focus");
repaint();
return true;
}
public boolean lostFocus(Event evt, Object arg)
{
showStatus("Lost focus");
repaint();
return true;
}
}

The getAppletInfo() and getParameterInfo() methods work hand in hand to provide information to an applet's user. Although the default versions of these methods only return a null string, you can override them in your applet in order to provide useful information.

The getAppletInfo() method should return a single string that contains at least the applet name, version, author, and copyright holder. The getParameterInfo() function must return a three-dimensional array of strings, with each row of strings in the array representing a single parameter for the applet. Each row must contain three strings: the parameter's name, type, and description. So, if your applet has only one parameter, you would have a string array with one row of three strings. If your applet has three parameters, you would have an array with three rows of three strings.

Confused? Listing 16.17 is a version of a previous applet, ConfigApplet3, modified in order to support the getAppletInfo() and getParameterInfo() methods. Listing 16.18 is the HTML document that loads and runs the applet, now called InfoApplet.

Listing 16.17 InfoApplet.java: An applet that supports getAppletInfo() and getParameterInfo().

import java.awt.*;
import java.applet.*;
public class InfoApplet extends Applet
{
String str;
Point position;
public void init()
{
HandleTextParam();
HandleTypeSizeParam();
HandlePositionParam();
}
public void paint(Graphics g)
{
g.drawString(str, position.x, position.y);
}
protected void HandleTextParam()
{
str = getParameter("text");
if (str == null)
str = "Default Text";
}
protected void HandleTypeSizeParam()
{
String s = getParameter("typesize");
if (s == null)
s = "24";
int typeSize = Integer.parseInt(s);
Font font = new Font("TimesRoman", Font.BOLD, typeSize);
setFont(font);
}
protected void HandlePositionParam()
{
String s = getParameter("xpos");
if (s == null)
s = "20";
int xpos = Integer.parseInt(s);
s = getParameter("ypos");
if (s == null)
s = "50";
int ypos = Integer.parseInt(s);
position = new Point(xpos, ypos);
}
public String getAppletInfo()
{
String info = "Info Applet by Clayton Walnum. ";
info = info + "Copyright 1995 by Macmillan Computer Publishing.";
return info;
}
public String[][] getParameterInfo()
{
String info[][] =
{{"text", "String", "Text to display"},
{"typesize", "int", "Size of the text"},
{"xpos", "int", "Column at which to display the text"},
{"ypos", "int", "Row at which to display the text"}};
return info;
}
}

Listing 16.18 INFOAPPLET.HTML: InfoApplet's HTML document.

<title>Applet Test Page</title>
<h1>Applet Test Page</h1>
<applet
code="InfoApplet.class"
width=640
height=200
name="InfoApplet">
<PARAM NAME=text VALUE="Hi there!">
<PARAM NAME=typesize VALUE=144>
<PARAM NAME=xpos VALUE=40>
<PARAM NAME=ypos VALUE=140>
</applet>

A Brief Look at the Panel, Container, and Component Classes

As I said previously, the Applet class inherits much of its functionality from a long inheritance tree that starts all the way back at the Panel class and works its way forward through Container and Component. Although these classes are important to Applet, they aren't defined in the java.applet package. Rather, you can find them in the java.awt package.

The Panel class represents any generic container, so it contains methods that are useful to any type of Java container. As it turns out, though, the only methods defined in Panel are the class's constructor and a method called addNotify(), neither of which are overly useful to an applet programmer. (Okay, you might want to construct a Panel object at one time or another, but I wouldn't lose any sleep over it.)

Stepping up to the Container class, which represents a container that can actually do something (rather than a generic do-nothing container), you find a lot of goodies. The more useful of these goodies are listed in table 16.2. For more information on these methods, consult Chapter 31, "java.awt" or Java's online documentation. Remember that, because Applet is derived from Component which is itself derived from Container, any of these methods are available to your applets, which are derived from Applet.

Table 16.2 Useful Methods of the Container Class

Method Description
add() Adds a component to the container.
countComponents() Gets the number of components in the container.
deliverEvent() Delivers an event to a component.
getComponent() Gets a reference to the given component.
getComponents() Gets an array of references to all the container's components.
getLayout() Gets a reference to the container's layout manager.
insets() Gets the size of the container's borders.
locate() Gets the component at the given coordinates.
minimumSize() Gets the container's minimum size.
preferredSize() Gets the container's preferred size.
remove() Removes a component from the container.
removeAll() Removes all components from the container.
setLayout() Sets the container's layout manager.

The greatest portion of an applet's functionality is inherited from the Component class, which is itself derived from Container. A component in Java represents just about every type of visible graphical element in an applet or application. For that reason, the Component class is a rich source of useful member functions, the most useful of which are listed in table 16.3. As you look over the table, you'll recognize many of these methods because you've used them in previous applets in this book. For more information on using these methods, consult Chapter 31, "java.awt."

Table 16.3 Useful Methods of the Component Class

Method Description
action() Responds to action events.
bounds() Gets the bounds of the component.
createImage() Creates an off-screen image.
deliverEvent() Delivers an event to the component.
disable() Disables the component.
enable() Enables the component.
getBackground() Gets the component's background color.
getFont() Gets the component's font.
getFontMetrics() Gets information about the component's font.
getForeground() Gets the component's foreground color.
getGraphics() Gets the component's Graphics object.
getParent() Gets a reference to the container's parent.
gotFocus() Responds to a got-focus message.
handleEvent() Responds to event on behalf of the component.
hide() Hides the component.
inside() Returns true if the component is within the given coordinates.
isEnabled() Returns true if the component is enabled.
isShowing() Returns true if the component is visible and the component's parent is also visible.
isVisible() Returns true if the component is visible.
keyDown() Responds to key-down events.
keyUp() Responds to key-up events.
locate() Gets the coordinate at the given location.
location() Gets the location of the component.
lostFocus() Responds to a lost-focus message.
minimumSize() Gets the component's minimum size.
mouseDown() Responds to mouse-down events.
mouseDrag() Responds to mouse-drag events.
mouseEnter() Responds to mouse-enter events.
mouseExit() Responds to mouse-exit events.
mouseMove() Responds to mouse-move events.
mouseUp() Responds to mouse-up events.
move() Moves the component to the given coordinates.
paint() Paints the component.
paramString() Gets this component's parameter string.
postEvent() Posts an event to the component.
preferredSize() Gets the component's preferred size.
reshape() Reshapes the component using the given bounding box.
resize() Resizes the component.
setBackground() Sets the component's background color.
setFont() Sets the component's font.
setForeground() Sets the component's foreground color.
show() Shows the component.
size() Gets the size of the component.
toString() Gets a string containing the component's values.
update() Updates the contents of the component.

Conclusion

Now you're ready to inundate the Web with your applet masterpieces. (Of course, you have to write those masterpieces first.) Still, you should keep reading this book in order to add new tricks to your Java programming skills. Most of the general Java programming techniques given in this book are also applicable to applets, so you won't want to miss anything.


Previous PageTOCNext Page

| Previous Chapter | Next Chapter |

| Table of Contents | Book Home Page |

| Que Home Page | Digital Bookshelf | Disclaimer |


To order books from QUE, call us at 800-716-0044 or 317-361-5400.

For comments or technical support for our books and software, select Talk to Us.

© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.