站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > Java Tutorial 5.0 英文版

How to Make Applets - Java Tutorial 5.0 英文版

The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components

How to Make Applets

This section covers JApplet — a class that enables applets to use Swing components. JApplet is a subclass of java.applet.Applet (in the API reference documentation), which is covered in the Applets (in the Creating a GUI with JFC/Swing trail) trail. If you've never written a regular applet before, we urge you to read that trail before proceeding with this section. The information provided in that trail applies to Swing applets, with a few exceptions that this section explains.

Any applet that contains Swing components must be implemented with a subclass of JApplet (in the API reference documentation). Here's a Swing version of one of the applets that helped make Java famous — an animation applet that (in its most well known configuration) shows our mascot Duke doing cartwheels: Your browser is completely ignoring the <APPLET> tag!


Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the J2SE JRE or SDK. We strongly recommend that you install the latest version; at least 1.3.1 is required for all our applets. You can find more information in the Java Plug-in home page.
You can find the main source code for this applet in TumbleItem.java (in a .java source file). See the examples index for links to all the files required by this example.

This section discusses the following topics:

Features Provided by JApplet

Because JApplet is a top-level Swing container, each Swing applet has a root pane. The most noticeable effects of the root pane's presence are support for adding a menu bar and the need to use a content pane.

As described in Using Top-Level Containers, each top-level container such as a JApplet has a single content pane. The content pane makes Swing applets different from regular applets in the following ways:

  • You add components to a Swing applet's content pane, not directly to the applet. Adding Components to the Content Pane shows you how.
  • You set the layout manager on a Swing applet's content pane, not directly on the applet.
  • The default layout manager for a Swing applet's content pane is BorderLayout. This differs from the default layout manager for Applet, which is FlowLayout.
  • You should not put painting code directly in a JApplet object. See Performing Custom Painting (in the Creating a GUI with JFC/Swing trail) for examples of how to perform custom painting in applets.

Threads in Applets

Swing components should be created, queried, and manipulated on the event-dispatching thread, but browsers don't invoke applet "milestone" methods from that thread. For this reason, the milestone methods — init, start, stop, and destroy — should use the SwingUtilities method invokeAndWait (or, if appropriate, invokeLater) so that code that refers to the Swing components is executed on the event-dispatching thread. More information about these methods and the event-dispatching thread is in How to Use Threads (in the Creating a GUI with JFC/Swing trail).

Here is an example of an init method:

public void init() {
    //Execute a job on the event-dispatching thread:
    //creating this applet's GUI.
    try {
        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                createGUI();
            }
        });
    } catch (Exception e) {
        System.err.println("createGUI didn't successfully complete");
    }
}

private void createGUI() {
    JLabel label = new JLabel(
                       "You are successfully running a Swing applet!");
    label.setHorizontalAlignment(JLabel.CENTER);
    label.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black));
    getContentPane().add(label, BorderLayout.CENTER);
}

The invokeLater method is not appropriate for this implementation because it allows init to return before initialization is complete, which can cause applet problems that are difficult to debug.

The init method in TumbleItem is more complex, as the following code shows. Like the first example, this init method implementation uses SwingUtilities.invokeAndWait to execute the GUI creation code on the event-dispatching thread. This init method also sets up two background threads to perform GUI-related tasks. First, it uses a Swing timer (in the Creating a GUI with JFC/Swing trail) (which uses a shared thread) to fire action events whenever the animation needs to be updated. Second, it uses a SwingWorker object (in the Creating a GUI with JFC/Swing trail) to create a background thread that loads the animation image files, letting the applet present a GUI before all its resources are available.

private void createGUI() {
    ...
    animator = new Animator();
    animator.setOpaque(true);
    animator.setBackground(Color.white);
    setContentPane(animator);
    ...
}

public void init() {
    loadAppletParameters();

    try {
        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                createGUI();
            }
        });
    } catch (Exception e) { 
        System.err.println("createGUI didn't successfully complete");
    }

    //Set up the timer that will perform the animation.
    timer = new javax.swing.Timer(speed, this);
    timer.setInitialDelay(pause);
    timer.setCoalesce(false);
    timer.start(); //Start the animation.

    //Loading the images can take quite a while, so to
    //avoid staying in init() (and thus not being able
    //to show the "Loading Images..." label) we'll
    //load the images in a SwingWorker thread.
    imgs = new ImageIcon[nimgs];
    final SwingWorker worker = new SwingWorker() {
        public Object construct() {
            ...//Load all the images...
            finishedLoading = true;
            return imgs;
        }

        //Executes in the event-dispatching thread.
        public void finished() {
            //Remove the "Loading images" label.
            animator.removeAll();
            loopslot = -1;
            animator.repaint();
        }
    };
    worker.start();
}

You can find the applet's source code in TumbleItem.java (in a .java source file). To find all the files required for the applet, including a link to a JNLP file that lets you run it using Java Web Start, see the example index.

Using Images in a Swing Applet

The Applet class provides the getImage method for loading images into an applet. The getImage method creates and returns an Image object that represents the loaded image. Because Swing components use Icons rather than Images to refer to pictures, Swing applets tend not to use getImage. Instead Swing applets create instances of ImageIcon — an icon loaded from an image file. ImageIcon comes with a code-saving benefit: it handles image tracking automatically. Refer to How to Use Icons (in the Creating a GUI with JFC/Swing trail) for more information.

The animation of Duke doing cartwheels requires 17 different pictures. The applet uses one ImageIcon per picture and loads them in its init method. Because images can take a long time to load, the icons are loaded in a separate thread implemented by a SwingWorker object (in the Creating a GUI with JFC/Swing trail). Here's the code:

public void init() {
    ...
    imgs = new ImageIcon[nimgs];
    ...
    final SwingWorker worker = new SwingWorker() {
        public Object construct() {
            //Images are numbered 1 to nimgs,
            //but fill array from 0 to nimgs-1.
            for (int i = 0; i < nimgs; i++) {
                imgs[i] = loadImage(i+1);
            }
            finishedLoading = true;
            return imgs;
        }
        ...
    };
    worker.start();
}
...
protected ImageIcon loadImage(int imageNum) {
    String path = dir + "/T" + imageNum + ".gif";
    int MAX_IMAGE_SIZE = 2400;  //Change this to the size of
                                 //your biggest image, in bytes.
    int count = 0;
    BufferedInputStream imgStream = new BufferedInputStream(
       this.getClass().getResourceAsStream(path));
    if (imgStream != null) {
        byte buf[] = new byte[MAX_IMAGE_SIZE];
        try {
            count = imgStream.read(buf);
            imgStream.close();
        } catch (java.io.IOException ioe) {
            System.err.println("Couldn't read stream from file: " + path);
            return null;
        }
        if (count <= 0) {
            System.err.println("Empty file: " + path);
            return null;
        }
        return new ImageIcon(Toolkit.getDefaultToolkit().createImage(buf));
    } else {
        System.err.println("Couldn't find file: " + path);
        return null;
    }
}
The loadImage method loads the image for the specified frame of animation. It uses the getResourceAsStream method rather than the usual getResource method to get the images. The resulting code isn't pretty, but getResourceAsStream is more efficient than getResource for loading images from JAR files into applets that are executed using Java Plug-inTM software. Moreover, for pre-1.4 versions of Java Plug-in, getResource can't be used to load resources from JAR files. For further details, see Loading Images Into Applets (in the Creating a GUI with JFC/Swing trail).

Embedding an Applet in an HTML Page

The recommended way to include an applet in an HTML page is using the APPLET tag. Here's the APPLET tag for the cartwheeling Duke applet:
<applet code="TumbleItem.class" 
        codebase="example-1dot4/"
        archive="tumbleClasses.jar tumbleImages.jar"
        width="600" height="95">
    <param name="maxwidth" value="120">
    <param name="nimgs" value="17">
    <param name="offset" value="-57">
    <param name="img" value="images/tumble">

Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>

Version note: Before version 1.3.1_01a, Java Plug-in required the OBJECT or EMBED tag instead of the APPLET tag. Details are available through the Java Plug-in home page (outside of the tutorial).
To find out about the various <APPLET> tag parameters, refer to Using the applet Tag (in the Creating a GUI with JFC/Swing trail) and Using the APPLET Tag  (in the Creating a GUI with JFC/Swing trail).

The JApplet API

The next table lists the interesting methods that JApplet adds to the applet API. They give you access to features provided by the root pane. Other methods you might use are defined by the Component (in the API reference documentation) and Applet (in the API reference documentation) classes. See Component Methods for a list of commonly used Component methods, and Applets (in the Creating a GUI with JFC/Swing trail) for help in using Applet methods.

Method Purpose
void setContentPane(Container)
Container getContentPane()
Set or get the applet's content pane. The content pane contains the applet's visible GUI components and should be opaque.
JRootPane createRootPane()
void setRootPane(JRootPane)
JRootPane getRootPane()
Create, set, or get the applet's root pane. The root pane manages the interior of the applet including the content pane, the glass pane, and so on.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar()
Set or get the applet's menu bar to manage a set of menus for the applet.
void setGlassPane(Component)
Component getGlassPane()
Set or get the applet's glass pane. You can use the glass pane to intercept mouse events.
void setLayeredPane(JLayeredPane)
JLayeredPane getLayeredPane()
Set or get the applet's layered pane. You can use the applet's layered pane to put components on top of or behind other components.

Applet Examples

This table shows examples of Swing applets and where those examples are described.

Example Where Described Notes
TumbleItem This page An animation applet
IconDemoApplet How to Use Icons (in the Creating a GUI with JFC/Swing trail) An applet for showing photos.


Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.