The JavaTM Tutorial

| 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`, which is covered in the Writing Applets 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`. 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`. See the examples index for links to all the files required by this example.

> This section discusses the following topics:

> - Features Provided by JApplet
> - Threads in Applets
> - Using Images in a Swing Applet
> - Embedding an Applet in an HTML Page
> - The JApplet API
> - Applet Examples

### 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 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.

> 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 (which uses a shared thread) to fire action events whenever the animation needs to be updated. Second, it uses a `SwingWorker` object 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`. 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 `Icon`s rather than `Image`s 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 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. 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.

### 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.

> To find out about the various <APPLET> tag parameters, refer to Test Driving an Applet and Using the APPLET Tag.

### 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` and `Applet` classes. See Component Methods for a list of commonly used `Component` methods, and Taking Advantage of the Applet API 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 | An applet for showing photos.

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

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