如何制作 Servlets
本节介绍JApplet
,这是一个使 applet 能够使用 Swing 组件的类。 JApplet
是java.applet.Applet的子类,该子类在Java Applets跟踪中进行了介绍。如果您以前从未编写过常规的 applet,我们建议您在 continue 本节之前先阅读该跟踪记录。该跟踪中提供的信息适用于 Swing 小应用程序,本节介绍了一些 exceptions。
任何包含 Swing 组件的 Servlets 都必须使用JApplet的子类来实现。这是一个使 Java 出名的 Servlets 的一个 Swing 版本-一个动画 Servlets(以其最著名的配置)显示了我们的吉祥物杜克在做手推车:
A browser with Javascript enabled is required for this page to operate properly\.
Note:
如果看不到 Servlets 正在运行,则需要至少安装Java SE 开发套件(JDK)7版本。
您可以在TumbleItem.java中找到此 Servlets 的主要源代码。
本节讨论以下主题:
JApplet 提供的功能
因为JApplet
是顶层 Swing 容器,所以每个 SwingServlets 都有一个根窗格。根窗格的存在最明显的效果是支持添加menu bar以及使用内容窗格的需要。
如使用顶层容器中所述,每个顶级容器(例如JApplet
)都具有一个内容窗格。内容窗格使 SwingServlets 与常规 Servlets 在以下方面有所不同:
-
您将组件添加到 SwingServlets 的内容窗格中,而不是直接添加到 Servlets 中。 将组件添加到内容窗格向您展示方法。
-
您在 SwingServlets 的内容窗格上而不是直接在 Servlets 上设置布局 管理 器。
-
SwingServlets 的内容窗格的默认布局 管理 器是
BorderLayout
。这不同于Applet
的默认布局 管理 器FlowLayout
。 -
您不应该将绘画代码直接放在
JApplet
对象中。有关如何在 Servlets 中执行自定义绘制的示例,请参见进行定制绘画。
Servlets 中的线程
应该在事件调度线程上创建,查询和操作 Swing 组件,但是浏览器不会从该线程调用 applet“里程碑”方法。因此,里程碑方法init
,start
,stop
和destroy
应该使用SwingUtilities
方法invokeAndWait
(或者,如果合适的话是invokeLater
),以便在事件派发线程上执行引用 Swing 组件的代码。有关这些方法和事件分发线程的更多信息,请参见Swing 中的并发。
这是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);
}
invokeLater
方法不适用于此实现,因为它允许init
在初始化完成之前返回,这可能导致难以调试的 applet 问题。
TumbleItem
中的init
方法更为复杂,如以下代码所示。与第一个示例一样,此init
方法实现使用SwingUtilities.invokeAndWait
在事件调度线程上执行 GUI 创建代码。此init
方法设置Swing timer来触发动作事件以更新动画。此外,init
使用javax.swing.SwingWorker创建一个后台任务,该后台任务加载动画图像文件,使该 applet 立即显示 GUI,而无需 await 所有资源被加载。
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();
}
您可以在TumbleItem.java中找到该 applet 的源代码。要查找 Servlets 所需的所有文件,请参见example index。
在 SwingServlets 中使用图像
Applet
类提供getImage
方法,用于将图像加载到 applet 中。 getImage
方法创建并返回一个Image
对象,该对象代表已加载的图像。由于 Swing 组件使用Icon
而不是Image
来引用图片,因此 Swing 小应用程序倾向于不使用getImage
。相反,SwingServlets 创建ImageIcon
的实例-从图像文件加载的图标。 ImageIcon
具有代码节省的好处:它可以自动处理图像跟踪。有关更多信息,请参考如何使用图标。
杜克(Duke)做车轮的动画需要 17 张不同的图片。Servlets 每张图片使用一个ImageIcon
并将其加载到其init
方法中。由于加载图像可能需要很 Long 时间,因此将图标加载到由SwingWorker
对象实现的单独线程中。这是代码:
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;
}
}
loadImage
方法为指定的动画帧加载图像。它使用getResourceAsStream
方法而不是通常的getResource
方法来获取图像。结果代码不是很漂亮,但是getResourceAsStream
比getResource
效率更高,可以将 JAR 文件中的图像加载到使用 Java Plug-in™软件执行的 applet 中。有关更多详细信息,请参见将图像加载到 Servlets。
将 Servlets 嵌入 HTML 页面
您可以使用applet
标签来部署一个简单的 applet。或者,您可以使用部署工具包。这是 the 脚的 DukeServlets 的代码:
<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>
有关更多信息,请参阅Java Applets类中的部署 Servlets。
JApplet API
下表列出了JApplet
添加到 applet API 的有趣方法。它们使您可以访问根窗格提供的功能。您可能使用的其他方法由Component和Applet类定义。有关常用Component
方法的列表,请参见Component Methods;有关使用Applet
方法的帮助,请参见Java Applets。
Method | Purpose |
---|---|
void setContentPane(Container) | |
Container getContentPane() | 设置或获取 Servlets 的内容窗格。内容窗格包含 Servlets 的可见 GUI 组件,并且应该是不透明的。 |
void setRootPane(JRootPane) JRootPane getRootPane() | 创建,设置或获取 Servlets 的根窗格。根窗格 管理Servlets 的内部,包括内容窗格,玻璃窗格等。 |
void setJMenuBar(JMenuBar) JMenuBar getJMenuBar() | 设置或获取 Servlets 的菜单栏,以 管理 该 Servlets 的菜单集。 |
void setGlassPane(Component) Component getGlassPane() | 设置或获取 Servlets 的玻璃窗格。您可以使用玻璃窗格来拦截鼠标事件。 |
void setLayeredPane(JLayeredPane) JLayeredPane getLayeredPane() | 设置或获取 Servlets 的分层窗格。您可以使用 Servlets 的分层窗格将组件放置在其他组件之上或之下。 |
Applet Example
下表显示了 SwingServlets 的示例,并在其中描述了这些示例。
Example | Where Described | Notes |
---|---|---|
TumbleItem | This page | 动画 Servlets |