Previous Page TOC Index Next Page

Chapter 23

The applet package and graphics

The Applet Package consists of several interfaces and the Applet class. (See Table 23.1.) The methods found in this class are used to construct applets and to provide basic functionality such as image and audio manipulation.

Table 23.1. The Applet Package.

Interfaces AppletContext
AppletStub
AudioClip
Class Applet

The AppletContext interface contains methods to access an applet’s environment, such as changing the URL displayed by the browser.

AppletStub is an interface that contains methods used to write an applet viewer, such as the AppletViewer provided by Sun in the Java Development Kit. Because these methods are necessary for interpreting applets, this interface is not used by applet programmers for creating the applets themselves.

AudioClip contains methods for manipulating audio from within your applets. Although the AudioClip interface is currently limited, it does offer basic sound capabilities. Future versions of Java undoubtedly will expand on the basic functionality of this interface.

The Graphics( ) class is a subclass of the AWT, and it contains the graphics methods. The methods found here can be used to create graphics primitives and perform simple graphics manipulations. This chapter only touches briefly on the Graphics class. Chapter 25,“Animation Programming,” will address some of the more advanced things you can do with the Graphics( ) methods.

NOTE
When programming graphics, most complex images can actually be broken down into smaller components known as primitives. These simple graphics building blocks such as a point, line, rectangle, oval, and polygon can be used in conjunction with each other to create more detailed shapes or images.

Characteristics of Applets

As stated in the overview, applets have limited functionality compared to full applications. For example, applets viewed on the web cannot do the following:

However, you still can use applets to create a variety of programs and enhance Web services. Keep in mind that for their limitations, applets do offer some advantages over applications. Because applets are executed within the AppletViewer or a Java-capable Web browser, some advanced features such as audio and image processing are utilized from the browser. This makes creating functional, visually interesting applets even easier.

The most important aspect of applets stems from the object-oriented nature of Java. Applets are objects. They are subclassed from the Panel object, which is in turn subclassed from Container. All of this subclassing has some advantages. Methods are passed down from one class to the next, and that means that you have a wide variety of methods available to you when programming your applets.

TIP
Keep Java’s object-oriented nature in mind when consulting the API documentation. If you are searching for a particular method for an object and are unable to find it, be sure to search up the class hierarchy. Because objects inherit the methods of classes they are subclassed from, if you travel up the hierarchy, you are apt to find the method you are looking for.

Applet Lifecycles

Applets have four lifecycle methods: init( ), start( ), stop( ), and destroy( ). These lifestyle methods can be used to control an applet at various stages of execution, and are called automatically. You can override any of these methods to perform specific tasks during execution, but it is not necessary to declare any of these methods.

init( )

init( ) is the first method called by an applet once it has been loaded by the AppletViewer or browser. Because it is called before the applet begins execution, it can be overridden to perform any initialization tasks, such as loading images, establishing the layout, or parsing parameter information. For example,

public void init( ) {

    clip = getAudioClip(getDocumentBase( ), soundfile.au);

    setLayout(new FlowLayout( ));

    play = new Button(“Play Clip”);

    add(play);

}

will load a specified audio file and create a layout with the button Play Clip. By loading any necessary files before the applet starts, you can avoid conflicts such as the applet trying to display an image that is not yet loaded.

start( )

When an applet has been loaded into the AppletViewer or browser, start( ) is called automatically to begin the actual execution of the applet. Start ( ) generally will contain the core of an applet. For example, the following code plays an audio file (clip).

public void start( ) {

        clip.play( );

}

stop( )

stop( ) is similar to start ( ). It is called automatically when an applet should stop execution—for example, when you leave an applet’s web page. stop( ) could be used to stop a sound file that is playing in a loop, or to stop any threads that might be executing.

public void stop( ) {

        clip.stop( );

}

destroy( )

destroy( ) is called when an applet has completely finished executing, and any resources allocated by the applet need to be returned to the system. Because Java takes care of garbage collection and memory allocation, it generally is not necessary to override destroy( ).

Leveraging the Browser

Because applets are executed within the environment of the AppletViewer or a Java-capable browser, applets can use some functions of the browser to their advantage. For example, applets use an HTML tag to specify parameters and pass information about the applet’s location. Applets also can use a browser’s capability to display images.

Locating Files

The HTML tag <applet> is used to place an applet on a web page or to invoke the AppletViewer. The applet, therefore, has a code base, and a document base.

The code base is the base URL of an applet itself, and the document base is the base URL of the HTML file that contains the applet. You can use the methods getCodeBase and getDocumentBase to obtain the base URLs to be used when loading image files or audio files. For example:

image = getImage(getDocumentBase( ), graphic);

will use the base URL of the applet HTML file to load image files.

Images

One of the biggest advantages applets gain by utilizing the browser is the ability to display images using the browser’s image decoder. This means that you can take advantage of GIF and JPEG file formats within your applets without writing any special code.

The two primary methods used in conjunction with images are getImage( ) and drawImage( ). The method getImage(URL, string) will accept a URL and a filename, and use that information to load a graphic file from the applet’s host machine into memory. For example,

image = getImage(getDocumentBase( ), “Me.gif”);

will load the file Me.gif from the host specified by the getDocumentBase( ) method. That image then can be used at will by the applet.

In order to view the image on the screen, it is necessary to use the method drawImage( ), which is actually a part of the Graphics class in the AWT.

//Draw an image on screen

import java.awt.*;

import java.applet.*;

import java.net.URL;

public class Pict extends java.applet.Applet {

    Image image;

    public void init( ) {

        image = getImage(getDocumentBase( ), “me.gif”);

    }

    public void paint(Graphics g) {

        g.drawImage(image, 0, 0, this);

    }

    public void start( ) {

        repaint( );

    }

}

In the preceding example, the applet follows some simple guidelines:

Using MediaTracker

The MediaTracker class enables you to establish a media tracking object that can monitor the status of loading images and inform your applet when the task is complete. Let’s take a look at the code necessary to utilize the MediaTracker class.

MediaTracker LoadImages;

Image slides[];

int images;

public void init( ) {

    for (int i = 0; i < images; i++) {

        slides[i] = getImage(getDocumentBase( ), imagefile + i + “.” + type);

            if (i > 0)

                LoadImages.addImage(slides[i], 1);

            else

                LoadImages.addImage(slides[i], 0);

    }

    try {

        LoadImages.waitForID(0);

    } catch (InterruptedException e) {

        System.out.println(“Image Loading Failed!”);

    }

    showStatus(imagefile + “ Images Loaded”);

    index = 0;

    repaint( );

    LoadImages.checkID(1,true);

}

In the preceding code, we create a media tracking object called LoadImages which will be responsible for tracking the loading of our images. We’ve created an array, slides[], to store the images that are loaded, and created an int variable images to represent the total number of images. The next step is to use our media tracking object in conjunction with getImage( ) to load our slides. We use the MediaTracker method addImage( ) to add each image to the list of images being tracked, and then we use checkID( ) with the true boolean to make sure that the images are loaded before proceeding.

Using MediaTracker to help you monitor status can be a safeguard for your applets. If you have an image-based animation, or some other graphics-intensive applet, it might be wise to use MediaTracker. As the name implies, MediaTracker is designed to be used with any media—graphics, audio, and so on. However, the current implementation of MediaTracker only supports images.

Audio

The Applet Package also contains methods for working with audio files. (See Table 23.2.)

Table 23.2. Audio methods.
getAudioClip( )
play( )
loop( )
stop( )

The getAudioClip( ) method can be found in java.applet.Applet and is used in the same manner as getImage( ). The remaining audio methods are contained in the AudioClip interface and exist to manipulate the file itself. These functions include the following:

play( ) Play an audio file until the end of the file.

loop( ) Play an audio file until the end, and repeat.

stop( ) Stop playing a sound file.

Loading and playing an audio file operates much like loading and playing images, as shown in the following:

import java.applet.*;

import java.lang.*;

import java.net.URL;

public class PlaySound extends Applet {

    AudioClip sound;

    public void init( ) {

    sound = getAudioClip(getDocumentBase( ), “hi.au”);

    }

    public void start( ) {

    sound.play( );

    }

}

Audio Limitations

Unfortunately, the methods currently provided for audio are quite limited. The audio methods currently only support .au format sound files. Additionally, the methods provided aren’t very robust. You only can play a sound file. There is no way to pause the file or clip a sound file. The lack of audio context methods means that your applets only can incorporate limited audio features, but the AudioClip interface is certainly an area that will be slated for improvement in future releases of the JDK.

Applet Contexts

The AppletContext interface contains methods that are useful for manipulating an applet’s environment. These methods allow the applet to exchange information with the browser to update web pages and to communicate applet status to the browser. The Applet Package contains the method getAppletContext( ), which allows the applet to obtain information about its environment, the AppletViewer, or a Web browser. This context information can then be used by the applet to the environment.

Using showDocument( )

Applets can be used to manipulate the browser itself. For example, an applet could function as an animated button on a Web page. An applet also could serve as a dynamic image map, providing users with instant status updates about the URLs contained in the map. In order to do that, an applet needs to be able to issue instructions to the browser. One of those instructions is showDocument( ). The showDocument( ) method can be used to send the browser to a new URL. It is evoked in the following manner:

try {

    getAppletContext( ).showDocument(new URL(url));

} catch (java.net.MalformedURLException e) {

    System.out.println(“URL Unreachable”);

}

This line of code obtains information about the environment that the applet running in and instructs that environment to go to another URL. Because of the nature of showDocument( ), it is important to monitor for errors. The try and catch syntax is very important when using showDocument( ). Because the method causes the browser to search over the Net for a URL, the success of this method depends on the availability of the given URL. Should the browser not be able to reach the specified URL, your applet needs to be instructed to catch any errors that might be generated.

Using showStatus( )

Often, an applet will want to communicate the status of an operation to the user. This can be accomplished with the showStatus( ) method. For example, when we looked at loading images using MediaTracker, the code contained the following line:

showStatus(imagefile + “ Images Loaded”);

This line of code called the showStatus( ) method to report when the images were finished loading. When an applet engages in tasks that might take a long time, showStatus( ) can be used to keep users informed of an applet’s progress. This can be advantageous when troubleshooting, and adds a level of user friendliness to your applets.

Getting Parameters

One of the most important aspects of the HTML files that evoke Java applets is the <param> tag. The parameter tag allows the applet user to specify the value of variables that will be passed to the applet. When your applet loads images or sound files, using parameters to pass the filenames to the applet can make your applet more flexible. Parameters also can be used to change the functionality of your applet. For example, the amount of delay between images in the SlideShow applet is defined by a parameter. The format for specifying parameters in an HTML files is as follows:

<HTML>

<applet code=”SlideShow.class”  width=400 height=250>

<param name=”caption” value=”A Sample Photo Album”>

</applet>

</HTML>

name specifies the parameter name and value specifies the parameter value passed to the applet. Parameters are established with the getParameterInfo( ) method. This method establishes an array containing an applet’s parameters and an information string that describes each parameter’s function. Let’s add the capability to accept parameters to our SlideShow example:

public class SlideShow extends Applet implements Runnable {

    String imagefile, soundfile, type, caption;

    int images, delay;

    public String[][] getParameterInfo( ) {

        String[][] info = {

            {“caption”, “string”, “Title of the Slide Viewer”},

            {“imagefile”, “string”, “Base Image File Name (ex. picture)”},

                  {“soundfile”, “string”, “Sound File Name (ex. audio.au)”},

                    {“images”, “int”, “Total number of image files”},

                  {“delay”, “int”, “Delay in between images (in ms.)”},

                  {“type”, “string”, “Image File Type(gif, jpg, etc)”},

        };    

        return info;

    }

    public void init( ) {

    caption = getParameter(“caption”);

    imagefile = getParameter(“imagefile”);

    soundfile = getParameter(“soundfile”);

    type    = getParameter(“type”);

    images  = Integer.valueOf(getParameter(“images”)).intValue( );

    delay   = Integer.valueOf(getParameter(“delay”)).intValue( );

    }

}

For example, in the code above, the line

{“caption”, “string”, “Title of the Slide Viewer”},

establishes the caption parameter, which is a string that represents the title of the SlideShow. Once parameters have been defined, they can be accessed using the getParameter( ) method. This method is used to obtain the value of a parameter and assign it to a variable within your applet. In the case of the SlideShow, parameters are used to specify the base imagefile name, the soundfile name, the number of images, the title of the viewer, and the delay between slides for the automatic slideshow option.

Graphics

One of Java’s primary attractions is the ability to spice up Web pages. What is a better way to spice up Web pages than animation and interaction? Before we can cover animation in Chapter 25 it is necessary to cover some basics concerning graphics in Java.

NOTE
The Graphics( ) methods are actually a part of the Abstract Windows Toolkit. However, because the AWT’s scope is so broad, we’ve broken the AWT up to make it a little more manageable. Keep in mind that graphics are listed under the AWT when consulting the API.

Java contains a number of graphics primitives that can enable you to begin creating basic shapes and minimal on-screen graphics quite quickly. Table 23.3 is a summary of some of the more useful Graphics methods. Keep in mind that these methods must be called within a graphics context. Java needs to be made aware of the graphics object you are manipulating in order to draw an on-screen graphic. For example

//Draw a Line

import java.awt.*;

import java.applet.*;

public class Line extends java.applet.Applet {

    public void paint(Graphics g) {

        g.drawLine(50,50,100,150);

    }

    public void start( ) {

        repaint( );

    }

}

produces the following output shown in Figure 23.1.

Figure FIGURE 23.1.

A line drawn using the drawLine ( ) method.

Here, the drawLine( ) method is used to draw a line between the points x1,y1 and x2,y2. The drawLine( ) method is evoked with the following line:

g.drawLine(50,50,100,150);

This line specifies the default graphics context (graphics object g), and a line from the point (50,50) to (100,150).

Table 23.3. A summary of Graphics contexts.

(x1,y1) and (x2,y2).
Method Result
Graphics( ) Constructs a new Graphics object.
create( ) Creates a new Graphics object.
dispose( ) Disposes of the current graphics context.
clearRect( ) Clears the specified rectangle using the current background color.
clipRect( ) Clips to a rectangle.
drawLine( ) Draws a line between two points
drawRect( ) Draws a rectangle using the current color.
drawRoundRect( ) Draws a rounded corner rectangle using the current color.
draw3DRect( ) Draws a 3-D rectangle.
drawOval( ) Draws an oval using the current color.
drawPolygon( ) Draws a polygon using an array of x points and y points.
drawString( ) Draws a string using the current font and color.
fillRect( ) Fills a rectangle using the current color.
fillRoundRect( ) Draws a filled rounded rectangle.
fill3DRect( ) Paints a 3-D rectangle filled with the current color.
fillOval( ) Fills an oval using the current color.
fillPolygon( ) Fills a polygon with the current color.
getColor( ) Gets the current color value.
setColor( ) Sets the current color value.
getFont( ) Gets the current font name.
setFont( ) Sets the font for all text operations.

The methods used to create ovals and rectangles are called in a similar fashion. Each method accepts four integer values to specify the starting point of the shape and its dimensions. Here are some examples (see Figures 23.2 and 23.3) of drawRect( ) and drawOval( ):

//Draw a Rectangle

import java.awt.*;

import java.applet.*;

public class Rectangle extends java.applet.Applet {

    public void paint(Graphics g) {

        g.drawRect(50,50,100,150);

    }

    public void start( ) {

        repaint( );

    }

}

Figure FIGURE 23.2.

A rectangle drawn with drawRect ( ).

//Draw an Oval public void paint(Graphics g) { g.drawOval(50,50,100,150); } Figure FIGURE 23.3.

An oval drawn with drawOval ( ).

Just as these methods can be used to create oval and rectangle outlines, fillRect( ) and fillOval( ) can be used to create solid shapes. (See Figure 23.4.) The code is quite similar:

//Draw Filled Shapes

import java.awt.*;

import java.applet.*;

public class Fills extends java.applet.Applet {

    public void paint(Graphics g) {

        g.setColor(Color.blue);

        g.fillRect(50,50,100,150);

        g.setColor(Color.red);

        g.fillOval(200,50,100,150);

    }

    public void start( ) {

        repaint( );

    }

}
Figure FIGURE 23.4.

A filleed oval and filled rectangle drawn using fillRect ( ) and fillOval ( ).

In addition to the basic rectangle and oval, the Graphics class also contains a method for creating polygons. The drawPolygon() method and fillPolygon() method can be used to create polygons containing any number of points. The methods accept integer arrays for the x and y values of the points, as in the following:

drawPolygon(int[], int[], int)

fillPolygon(int[], int[], int)

The last integer accepted is the total number of points contained in the polygon and the closing point. When creating polygons, keep in mind the following caveats:

Keeping those ideas in mind, drawing a polygon (see Figure 24.5) can actually be quite easy, as in the following:

//Draw a Polygon and Filled Polygon

import java.awt.*;

import java.applet.*;

public class Poly extends java.applet.Applet {

    int x[] = {100,200,250,50,100};

    int y[] = {50,50,200,200,50};

    int a[] = {300,350,400,300};

    int b[] = {200,50,200,200};

    public void paint(Graphics g) {

        g.drawPolygon(x,y,5);

        g.setColor(Color.blue);

        g.fillPolygon(a,b,4);

    }

    public void start( ) {

        repaint( );

    }

}
Figure FIGURE 23.5.

Examples of filled and unfilled polygons.

In the preceding examples, we’ve also used the setColor() method. The setcolor method can be used to change the drawing color used by any method in the Graphics class. The setColor() method can accept a number of predefined color variables (such as red and blue) or can accept RGB color values.

These are the basic graphics methods you need to get started creating images in your applets. Chapter 25 will discuss some more advanced uses for these methods, such as animation.

A Sample Applet: SlideShow

SlideShow is a simple photo gallery application that can be used to set up a slide show of images (see Figure 23.6). The application accepts the following several parameters:

Figure FIGURE 23.6.

The SlideShow in action: an image of the author hard at work.

The structure of this applet is fairly straightforward. The layout consists of the image to be displayed and some simple controls. The “AutoCycle images” button enables and disables the automatic slide show feature, and the “Sound On” button enables the user to turn the sound off. Previous and Next buttons are provided to enable users to cycle through the slides at their own pace.

The applet itself loads the images using MediaTracker during the Init() state, and then begins a thread for the automatic show. The activity of the thread is then controlled by the check box.

The check boxes and buttons are monitored for action events. If an action event is detected from one of the check boxes, the thread and audio are stopped or started as appropriate. The buttons also are monitored for action events, which simply increment or decrement the index counter. The end result is a simple SlideShow applet that enables you to have an automatic show or control your own images.

The HTML file for the SlideShow applet is as follows:

<HTML>

<applet code=”SlideShow.class”  width=400 height=250>

<param name=”caption” value=”A Sample Photo Album”>

<param name=”imagefile” value=”image”>

<param name=”soundfile” value=”song.au”>

<param name=”images” value=”5">

<param name=”delay” value=”5000">

<param name=”type” value=”gif”>

</applet>

</HTML>

Listing 23.1 is the complete code for the SlideShow applet.

/* A simple Slide Viewer */

import java.awt.*;

import java.lang.*;

import java.applet.*;

import java.net.URL;

public class SlideShow extends Applet implements Runnable {

    MediaTracker LoadImages;

    Image slides[];

    String imagefile, soundfile, type, caption;

    Thread AutoShow;

    int images, delay;

    int index = 0;

    Button forward, backward;

    Checkbox auto, sound;

    Label title;

      AudioClip clip;

    Panel marquee, control;

    public String[][] getParameterInfo() {

        String[][] info = {

            {“caption”, “string”, “Title of the Slide Viewer”},

            {“imagefile”, “string”, “Base Image File Name (ex. picture)”},

                  {“soundfile”, “string”, “Sound File Name (ex. audio.au)”},

                    {“images”, “int”, “Total number of image files”},

                  {“delay”, “int”, “Delay in between images (in ms.)”},

                  {“type”, “string”, “Image File Type(gif, jpg, etc)”},

        };

        return info;

    }

    public void init() {

    //Parse the parameters from the HTML file

    LoadImages = new MediaTracker(this);

    caption = getParameter(“caption”);

    imagefile = getParameter(“imagefile”);

    soundfile = getParameter(“soundfile”);

    type    = getParameter(“type”);

    images  = Integer.valueOf(getParameter(“images”)).intValue();

    slides = new Image[images];

    delay   = Integer.valueOf(getParameter(“delay”)).intValue();

    //Use MediaTracker to load the images

    for (int i = 0; i < images; i++) {

        slides[i] = getImage(getDocumentBase(), imagefile + i + “.” + type);

            if (i > 0)

                LoadImages.addImage(slides[i], 1);

            else

                LoadImages.addImage(slides[i], 0);

    }

    try {

        LoadImages.waitForID(0);

    } catch (InterruptedException e) {

        System.out.println(“Image Loading Failed!”);

    }

    showStatus(imagefile + “ Images Loaded”);

    index = 0;

    repaint();

    LoadImages.checkID(1,true);

    clip = getAudioClip(getDocumentBase(), soundfile);

    //Create the SlideViewer layout

    setLayout(new BorderLayout());

    forward = new Button(“Next”);

    backward = new Button(“Previous”);

    auto = new Checkbox(“AutoCycle Images”);

    auto.setState(true);

    sound = new Checkbox(“Sound On”);

    sound.setState(true);

    title = new Label(caption);

    Panel marquee = new Panel();

    marquee.setLayout(new BorderLayout());

    marquee.add(“North”, title);

    Panel control = new Panel();

    control.setLayout(new FlowLayout());

    control.add(auto);

    control.add(sound);

    control.add(backward);

    control.add(forward);

    setFont(new Font(“Helvetica”, Font.BOLD, 18));

    add(“South”, marquee);

    setFont(new Font(“Helvetica”, Font.PLAIN, 14));

    marquee.add(“South”, control);

    }

    //Monitor checkboxes and buttons for actions

    public boolean action(Event evt, Object what) {

        if (evt.target == sound) {

            if (sound.getState() == true)

                clip.loop();

            else

                clip.stop();

            return true;

        } else if (evt.target == backward) {

            if (index !=0) {

                index--;

                repaint();

            }

            return true;

        } else if (evt.target == forward) {

            index++;

            repaint();

            return true;

            } else

            return false;

    }

    public void start() {

        images = 0;

        repaint();

        clip.loop();

        AutoShow = new Thread(this);

        AutoShow.start();

    }

    public void stop() {

        index = 0;

        repaint();

        if (AutoShow!= null) AutoShow.stop();

        AutoShow= null;

    }

    public void run() {

        Thread running = Thread.currentThread();

        while (AutoShow==running) {

            try {

                Thread.sleep(delay);

            } catch (InterruptedException e) {

                break;

            }

                if (auto.getState() == true) {

                    if (LoadImages.checkID(1,true))

                        synchronized (this) {

                            if (index == (slides.length - 1))

                                index = 0;

                            else

                                index++;

                            }

                        repaint();

                    }

        }

       }

    //Update is called by repaint()

    public void update(Graphics g) {

        try {

            paint(g);

        } catch (ArrayIndexOutOfBoundsException e) {

            if(index < 0)

                index = 0;

            else if (index > images)

                index = images;

            System.out.println(“No more Images!”);

        }

    }

    //Paint the slide image on the screen

    //and account for missing images

    public void paint(Graphics g) {

        if (LoadImages.isErrorAny()) {

            g.setColor(Color.black);

            g.fillRect(0, 0, size().width, size().height);

            return;

        }

        g.drawImage(slides[index], 0, 0, this);

    }

}

Summary

With the methods found in the AWT and in the Applet Package you have all the tools you need to create applets on your own. Understanding the lifecycle of applets can help you make your applets more efficient and ensure they function correctly. You should also be able to handle images and audio files and have a basic understanding of graphics. Now that the building blocks for applets are under your command, let’s move on to Chapter 24, “Programming Applets,” and look at some practical implementations of these techniques.


Previous Page TOC Index Next Page