Documentation

The Java™ Tutorials
Hide TOC
How to Make Applets如何制作小程序
Trail: Creating a GUI With Swing
Lesson: Using Swing Components
Section: How to Use Various Components

How to Make Applets如何制作小程序

This section covers JApplet — a class that enables applets to use Swing components. 本节涵盖JApplet—使小应用程序能够使用Swing组件的类。JApplet is a subclass of java.applet.Applet, which is covered in the Java Applets trail. java.applet.Applet的一个子类,在Java小程序教程中有介绍。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.该指南中提供的信息适用于Swing小程序,本节将解释一些例外情况。

Any applet that contains Swing components must be implemented with a subclass of JApplet. 任何包含Swing组件的applet都必须用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:以下是帮助Java成名的小程序之一的Swing版本—一个动画小程序(在其最著名的配置中)显示吉祥物杜克正在做侧翻:


Note:  If you don't see the applet running, you need to install at least the Java SE Development Kit (JDK) 7 release.如果您没有看到小程序正在运行,则至少需要安装JavaSE开发工具包(JDK)7版本。

You can find the main source code for this applet in TumbleItem.java.您可以在TumbleItem.java中找到此小程序的主要源代码。

This section discusses the following topics:本节讨论以下主题:

Features Provided by JAppletJApplet提供的功能

Because JApplet is a top-level Swing container, each Swing applet has a root pane. 因为JApplet是一个顶级Swing容器,所以每个Swing小程序都有一个根窗格。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. 使用顶级容器中所述,每个顶级容器(如JApplet)都有一个内容窗格。The content pane makes Swing applets different from regular applets in the following ways:内容窗格通过以下方式使Swing小程序与常规小程序不同:

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. Swing组件应该在事件调度线程上创建、查询和操作,但浏览器不会从该线程调用applet“里程碑”方法。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. 因此,里程碑方法—initstartstopdestory;应使用SwingUtilities方法invokeAndWait(或者,如果合适,使用invokeLater),以便在事件调度线程上执行引用Swing组件的代码。More information about these methods and the event-dispatching thread is in Concurrency in Swing.有关这些方法和Swing中并发的事件调度线程的更多信息。

Here is an example of an init method:以下是init方法的示例:

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.invokeLater方法不适用于此实现,因为它允许init在初始化完成之前返回,这可能会导致难以调试的小程序问题。

The init method in TumbleItem is more complex, as the following code shows. TumbleItem中的init方法更复杂,如下代码所示。Like the first example, this init method implementation uses SwingUtilities.invokeAndWait to execute the GUI creation code on the event-dispatching thread. 与第一个示例类似,此init方法实现使用SwingUtilities.invokeAndWait在事件调度线程上执行GUI创建代码。This init method sets up a Swing timer to fire action events the update the animation. 这个init方法设置了一个Swing定时器来触发动作事件以更新动画。Also, init uses javax.swing.SwingWorker to create a background task that loads the animation image files, letting the applet present a GUI right away, without waiting for all resources to be loaded.此外,init使用javax.swing.SwingWorker创建一个加载动画图像文件的后台任务,让applet立即呈现GUI,而无需等待加载所有资源。

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

public void init() {
    loadAppletParameters();

    //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");
    }

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

    //Background task for loading images.
    SwingWorker worker = (new SwingWorker<ImageIcon[], Object>() {
            public ImageIcon[] doInBackground() {
                final ImageIcon[] innerImgs = new ImageIcon[nimgs];
            ...//Load all the images...
            return imgs;
        }
        public void done() {
            //Remove the "Loading images" label.
            animator.removeAll();
            loopslot = -1;
            try {
                imgs = get();
            } ...//Handle possible exceptions
        }

    }).execute();
}

You can find the applet's source code in TumbleItem.java. 您可以在TumbleItem.java中找到小程序的源代码。To find all the files required for the applet, see the example index.要查找小程序所需的所有文件,请参阅示例索引

Using Images in a Swing Applet在Swing小程序中使用图像

The Applet class provides the getImage method for loading images into an applet. Applet类提供了用于将图像加载到Applet中的getImage方法。The getImage method creates and returns an Image object that represents the loaded image. getImage方法创建并返回表示加载图像的Image对象。Because Swing components use Icons rather than Images to refer to pictures, Swing applets tend not to use getImage. 因为Swing组件使用Icon而不是Image来引用图片,所以Swing小程序倾向于不使用getImageInstead Swing applets create instances of ImageIcon — an icon loaded from an image file. 相反,Swing小程序创建ImageIcon—从图像文件加载的图标。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. 杜克做车轮的动画需要17张不同的图片。The applet uses one ImageIcon per picture and loads them in its init method. 小程序在每张图片上使用一个ImageIcon,并在其init方法中加载它们。Because images can take a long time to load, the icons are loaded in a separate thread implemented by a SwingWorker object. 由于图像可能需要很长时间才能加载,因此图标将加载到由SwingWorker对象实现的单独线程中。Here's the code:下面是代码:

public void init() {
    ...
    imgs = new ImageIcon[nimgs];
    (new SwingWorker<ImageIcon[], Object>() {
        public ImageIcon[] doInBackground() {
            //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);
            }
            return imgs;
        }
        ...
    }).execute();

}
...
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. loadImage方法为指定的动画帧加载图像。It uses the getResourceAsStream method rather than the usual getResource method to get the images. 它使用getResourceAsStream方法而不是通常的getResource方法来获取图像。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-in™ software. 生成的代码并不漂亮,但是对于将JAR文件中的图像加载到使用Java插件™软件执行的小程序,getResourceAsStreamgetResource更高效。For further details, see Loading Images Into Applets.有关详细信息,请参阅将图像加载到小程序中

Embedding an Applet in an HTML Page在HTML页面中嵌入小程序

You can deploy a simple applet by using the applet tag. 您可以使用applet标记部署一个简单的appletOr, you can use the Deployment Toolkit. 或者,您可以使用部署工具包。Here is the code for the cartwheeling Duke applet:下面是Cartweeling Duke小程序的代码:

<script src="https://www.java.com/js/deployJava.js" type="text/javascript">
</script><script type="text/javascript">
//<![CDATA[
    var attributes = { archive: 'https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/TumbleItemProject/TumbleItem.jar',
                       codebase: 'https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/TumbleItemProject',
                       code:'components.TumbleItem', width:'600', height:'95' };
    var parameters = { permissions:'sandbox', nimgs:'17', offset:'-57',
                       img: 'images/tumble', maxwidth:'120' };
    deployJava.runApplet(attributes, parameters, '1.7');
//]]>
</script><noscript>A browser with Javascript enabled is required for this page to operate properly.</noscript>

For more information, see Deploying an Applet in the Java Applets lesson.有关详细信息,请参阅Java小程序课程中的部署小程序

The JApplet APIJApplet API

The next table lists the interesting methods that JApplet adds to the applet API. 下表列出了JApplet添加到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. 您可能使用的其他由ComponentApplet类定义的方法。See Component Methods for a list of commonly used Component methods, and Java Applets for help in using Applet methods.有关常用Component方法的列表,请参阅组件方法;有关使用Applet方法的帮助,请参阅Java小程序

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.内容窗格包含小程序的可见GUI组件,应该是不透明的。
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 Example小程序示例

This table shows examples of Swing applets and where those examples are described.下表显示了Swing小程序的示例以及这些示例的描述位置。

Example实例 Where Described描述位置 Notes备注
TumbleItem This page本页 An animation applet动画小程序

Previous page: How to Use Various Components
Next page: How to Use Buttons, Check Boxes, and Radio Buttons