这些Java教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言更改,了解Java SE 9及后续版本中更新的语言特性的概述。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息。
本节介绍了 JApplet
—— 一个使applet能够使用Swing组件的类。 JApplet
是 java.applet.Applet
的子类,该类在 Java Applets 部分有详细介绍。如果您以前从未编写过普通的applet,请在阅读本节之前阅读该部分。该部分提供的信息适用于Swing applet,但也有一些例外情况,本节会进行解释。
包含Swing组件的任何applet必须使用 JApplet
的子类来实现。下面是一个Swing版本的帮助Java走红的applet之一 —— 一个动画applet,最著名的配置是显示我们的吉祥物Duke做空翻:
您可以在 TumbleItem.java
中找到该applet的主要源代码。
本节讨论以下主题:
由于JApplet
是一个顶级的Swing容器,每个Swing applet都有一个根窗格。根窗格的最明显的特点是支持添加一个 菜单栏,以及使用内容窗格的需求。
如在使用顶层容器中所描述的,每个顶层容器,如JApplet
,都有一个单独的内容窗格。内容窗格使得Swing applet与普通applet有以下不同之处:
BorderLayout
。这与Applet
的默认布局管理器FlowLayout
不同。JApplet
对象中放置绘图代码。请参见执行自定义绘图中有关如何在applet中执行自定义绘图的示例。Swing组件应该在事件调度线程上创建、查询和操作,但浏览器不会从该线程调用applet的“里程碑”方法。因此,里程碑方法init
、start
、stop
和destroy
应该使用SwingUtilities
的invokeAndWait
方法(或者如果适用的话,invokeLater
),以便引用Swing组件的代码在事件调度线程上执行。有关这些方法和事件调度线程的更多信息,请参见Swing中的并发。
下面是一个init
方法的示例:
public void init() { //在事件调度线程上执行一个任务: //创建这个applet的GUI。 try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { createGUI(); } }); } catch (Exception e) { System.err.println("createGUI没有成功完成"); } } private void createGUI() { JLabel label = new JLabel( "您正在成功运行一个Swing applet!"); label.setHorizontalAlignment(JLabel.CENTER); label.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black)); getContentPane().add(label, BorderLayout.CENTER); }
这个实现中invokeLater
方法不适用,因为它允许init
在初始化完成之前返回,这可能会导致难以调试的applet问题。
如下所示,TumbleItem
中的init
方法更复杂。与第一个示例类似,这个init
方法实现使用SwingUtilities.invokeAndWait
在事件调度线程上执行GUI创建代码。此init
方法设置了一个Swing定时器来触发更新动画的动作事件。此外,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(); //在事件调度线程上执行一个任务:创建此小程序的GUI。 try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { createGUI(); } }); } catch (Exception e) { System.err.println("createGUI没有成功完成"); } //设置执行动画的计时器。 timer = new javax.swing.Timer(speed, this); timer.setInitialDelay(pause); timer.setCoalesce(false); timer.start(); //启动动画。 //用于加载图像的后台任务。 SwingWorker worker = (new SwingWorker<ImageIcon[], Object>() { public ImageIcon[] doInBackground() { final ImageIcon[] innerImgs = new ImageIcon[nimgs]; ...//加载所有图像... return imgs; } public void done() { //移除“正在加载图像”的标签。 animator.removeAll(); loopslot = -1; try { imgs = get(); } ...//处理可能的异常 } }).execute(); }
你可以在TumbleItem.java中找到小程序的源代码。要找到小程序所需的所有文件,请参阅示例索引。
Applet
类提供了getImage
方法来加载图像到小程序中。 getImage
方法创建并返回表示加载的图像的Image
对象。因为Swing组件使用Icon
而不是Image
来引用图片,所以Swing小程序往往不使用getImage
。相反,Swing小程序创建ImageIcon
的实例 - 从图像文件加载的图标。 ImageIcon
自动处理图像跟踪,这是它的一个节省代码的好处。请参阅如何使用图标以获取更多信息。
杜克做手脚的动画需要17张不同的图片。小程序使用每张图片一个ImageIcon
,并在其init
方法中加载它们。由于图像可能需要很长时间来加载,这些图标是在由SwingWorker
对象实现的单独线程中加载的。以下是代码:
public void init() { ... imgs = new ImageIcon[nimgs]; (new SwingWorker<ImageIcon[], Object>() { public ImageIcon[] doInBackground() { //从1到nimgs编号的图像, //但将数组从0到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; //将此值更改为最大图像的大小(以字节为单位)。 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("无法从文件读取流:" + path); return null; } if (count <= 0) { System.err.println("空文件:" + path); return null; } return new ImageIcon(Toolkit.getDefaultToolkit().createImage(buf)); } else { System.err.println("找不到文件:" + path); return null; } }
loadImage
方法加载指定动画帧的图像。它使用 getResourceAsStream
方法而不是通常的 getResource
方法来获取图像。由于使用 Java Plug-in™ 软件在 JAR 文件中加载图像的 applet 中,getResourceAsStream
方法比 getResource
方法更高效。有关详细信息,请参阅 将图像加载到 Applet 中。
您可以使用 applet
标签部署简单的 applet。或者,您可以使用 Deployment Toolkit。这是 cartwheeling Duke applet 的代码:
<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>启用 JavaScript 的浏览器才能正常运行此页面。</noscript>
下表列出了JApplet
在小程序API中添加的有趣方法。它们使您能够访问根窗格提供的功能。您可能会使用的其他方法由Component
和Applet
类定义。有关常用Component
方法的列表,请参阅组件方法,有关使用Applet
方法的帮助,请参阅Java小程序。
方法 | 用途 |
---|---|
void setContentPane(Container) Container getContentPane() |
设置或获取小程序的内容窗格。内容窗格包含小程序的可见GUI组件,并应该是不透明的。 |
void setRootPane(JRootPane) JRootPane getRootPane() |
创建、设置或获取小程序的根窗格。根窗格管理小程序的内部,包括内容窗格、玻璃窗格等。 |
void setJMenuBar(JMenuBar) JMenuBar getJMenuBar() |
设置或获取小程序的菜单栏,以管理一组菜单。 |
void setGlassPane(Component) Component getGlassPane() |
设置或获取小程序的玻璃窗格。您可以使用玻璃窗格拦截鼠标事件。 |
void setLayeredPane(JLayeredPane) JLayeredPane getLayeredPane() |
设置或获取小程序的分层窗格。您可以使用小程序的分层窗格将组件放在其他组件的上方或下方。 |
这个表格展示了Swing applet的示例以及这些示例的描述。
示例 | 描述位置 | 注释 |
---|---|---|
TumbleItem |
本页 | 一个动画applet |