引言
一张湘绣汇集了湘女累月
心血,我们称之为劳动密集型,一块芯片集聚着众多高新
科技,我们称之为技术密集型,一个实例承载了丰富
知识点,是否可以称为知识密集型呢:)?用一张网捞到更多
鱼是渔夫
追求,通过一个实例学到更多
知识点则是我们这些开发人员
企盼。
本文拟通过一个耳熟能详
指法练习游戏讲解如何在JBuilder 2005下开发Applet应用程序,通过本文,你将可以学习到图形用户界面开发、动画处理、声音播放、事件处理、多线程、I/O读写、Applet打包、Applet安全模型、数字签名、JRE插件制作、JDK5.0等方面
知识,并适时介绍笔者一些开发经验。 字串1
指法练习Applet游戏介绍 字串6
1、界面及功能 字串4
指法练习
Applet游戏
界面如下图所示: 字串6
字串4
图 1 指法练习
用户界面
字串8
如上图所示,这个Applet共由11个组件组成,左边
主界面是画布Canvas组件,被分隔为10个栏。程序会随机在这些栏中产生下落
字母,用户按下匹配
字母键盘按键后,即为击中,相应
字母将消失,正确数递增1;字母落到画布底端后,还没有被击中,失败数递增1;每产生一个下落
字母,总数递增1。 字串6
游戏提供了3个JButton
按钮,分别用于控制游戏
开始/暂停、结束以及保存游戏成绩。在未启动游戏前第一个按钮显示为三角箭头
图标,点击后启动游戏,随后按钮图标切换为暂停
图标。而第二个为停止按钮,其上显示结束
图标,当游戏处于运行或暂停
状态时,点击该按钮将停止游戏以便重新开始。而第三个按钮保存游戏
成绩到客户端
D:
esult.txt文件中。 字串1
整个界面采用BorderLayout布局管理器,画布位于BorderLayout.CENTER区,而右边
控制台JPanel位于BorderLayout.EAST区。控制台
JPanel采用GridLayout布局管理器。 字串6
2、程序组成 字串1
每个下落
字母对应一个线程实例,称为DropCharThread线程,它由一个产生器定时产生出来,这个产生器也是一个线程称为GenerateDropThread线程,下面是这个Applet
类图:
字串5
字串5
图 2 Applet类图
TypeTrainApplet类继承了JApplet,是游戏
主类,DropCharThread和GenerateDropThread都是其内部类,后两者都继承Thread,以线程
方式运行,下面对这3个类重要
成员变量和成员方法进行说明。
1).TypeTrainApplet 字串5
继承JApplet
Applet主类,负责构造用户界面、响应用户操作事件、更新游戏统计数据等。
字串8
· 重要成员变量 字串3
统计数据变量 字串3
volatile int totalCount = 0;//生产下落字母
总数。
volatile int rightCount = 0;//正确击中
字母数。
volatile int errorCount = 0;//未被击中且到达画布底部
字母数。 这3个变量用volatile作了修饰,这是因为这3个变量会被每个字母下落线程更改,为防止各个线程通过各自
缓存更改变量值造成线程间值
不同步,需要将这3个变量设置为volatile
类型,这样这些变量
更改值对于其他线程马上可见。 字串9
字母下落速率控制变量
字串7
private static int stepLen = 2; //每次下落
步长,即字母每移一步
象素。
private static int stepInterval = 50; //每两步之间
时间间隔,以毫秒为单位。
private static int columnCount = 10; //画布被分隔为多个栏
private static int generateInterval = 500; //创建一个新
下落字母线程
时间间隔,以毫秒为单位 Applet通过通过这4个变量达到控制产生字母
快慢和字母下落
速度及栏数,可以进一步规划这些值,以形成游戏
难度级别。有鉴于此,我们特地将这些参数
值通过HTML
<Applet>参数传入。这样,只需要更改HTML
<applet>参数值就可以达到控制游戏难度级别
目标,而不需更改Applet程序。 字串9
其他
字串7
int colWidth; //下落字母每栏
宽度,在运行期才获取这个变量值,它由画布
宽度和栏数决定。
volatile char pressKeyChar; //记录当前按键对应
字母。
int statusCode = 0; //记录游戏所处
状态,其中1:运行态、,2:暂停态 0:停止态。· 重要成员方法
private void drawResult()//将统计结果写到界面
对应JLabel中。
private void resetGame()//重置游戏现场2) DropCharThread 字串4
是一个线程,将一个随机
字母在画布
特定栏中往下落下,并实时检测是否被击中,如果击中马上消失,否则一直落到画布
底部。
·重要成员变量 字串8
char c; //对应
字母
int colIndex; //对应画布
栏序号,第一栏为1,第二栏为2,以此类推
int x, y; //当前字母在画布中
坐标·动作类型常量
字串5
private static final int ACTION_DRAW_FONT = 1; //表示画字符
private static final int ACTION_CLEAR_FONT = 2; //表示清除字符 不应当直接用1或2表示动作
类型,而应该定义一个更有意义
常量,这样不但于理解,也便于以后
维护。 字串8
·重要成员方法
public DropCharThread(char c, int colIndex)//构造函数,传入特定
字母和栏序号
private void draw(int actionType)//在画布中特写
位置上画字母3) GenerateDropThread 字串9
·重要成员变量 字串2
Random random = new Random(); //负责产生随机数·重要成员方法
private char getRandomChar()//获取一个随机
字母 负责定时产生一个DropCharThread线程实例,通过generateInterval成员变量控制产生DropCharThread线程实例
频率。 字串9
当游戏玩家点击Applet
开始按钮后,Applet将启动游戏,这3个类之间
交互关系可以通过以下
顺序图来描述,如下图所示: 字串3
字串5
图 3 开始游戏
顺序图
字串8
1)当用户按下Applet
开始按钮后激发一个事件。
2) Applet响应这个事件,调用事件响应方法,在方法中实例化一个GenerateDropThread线程,并启动这个线程。
字串7
3) GenerateDropThread线程定时产生一个DropCharThread线程,并让赋予一个随机
字母和栏序号。
4)DropCharThread线程启动,将字母在特定
栏中从上至下落下。 字串7
程序框架
1、利用向导生成Applet
字串4
首先创建一个工程(File->New...->Project->双击Project页中
Project图标),我们将工程名取为game,然后利用下面
步骤,调用Applet向导生成TypeTrainApplet。
字串6
1) 启动Applet向导 字串1
File->New...->Web->双击Web页中Applet
图标启动共4步
Applet向导。
字串3
2) 向导第1步,填写Applet
详细信息。 字串5
字串2
图 4 Applet向导第1步 字串7
·ClassName:Applet
类名,填入TypeTrainApplet 字串6
·Package:包名,接受默认值 字串5
·Base Class:父类,有两个选项,一个是java.applet.Applet,另一个是javax.swing.JApplet。前者以AWT为基础,而后者以Swing为基础。如果客户端浏览器
JRE版本很低,且你不希望客户下载额外
插件,则需要考虑用java.applet.Applet,且不能应用高版本JDK中
特性,这里我们用javax.swing.JApplet。
字串8
·Generate header comments:在产生Applet代码时,产生类标题头
注释说明,你大可不必生成这些注释。
字串3
·Can run standalone:是否将Applet设置为可独立运行,如果勾选,JBuilder为其生成了一个main函数,这样就可以在脱离浏览器或AppletViewer
情况下,像一般可运行类一样运行这个Applet中
功能,我们不勾选它。 字串8
·Generate standard methods:是否生成Applet
标准函数,大家都知道Applet通过4个函数管理着Applet
生命周期,它们分别是init()、start()、stop()、destroy()。如果不勾选这个选项,向导只会生成init()方法,而其他3个方法不会生成。在我们
例子中,需要用到其他3个方法,所以需要勾选。
按Next到下一步。 字串5
3) 定义Applet
参数 字串9
Applet
参数是指通过网页中<applet>标签
<param>指定
参数值,这些值可以在Applet类中引用到。这样就允许在不改变Applet程序
情况下,仅通过网页中<applet>属性值
更改控制Applet
表现。我们在这一步中为Applet设置4个控制变量参数,如下图所示:
字串9
字串2
图 5 为Applet设置参数 字串4
这一步
设置,不但为网页生成了参数声明,还为Applet程序生成了从网页获取参数值
方法,在Applet初始化时,即将网页中
参数值赋给Applet
成员变量。 字串8
点击Add Parameter新增一行,声明一个新
参数,其中Name*为网页中参数
名字,而Variable*为Applet类成员变量名,通过Type*栏设置成员变量
数据类型。你还可以为参数在Default栏中指定一个默认
值,在Desc中给出描述说明信息,其中带*
栏是必填
栏。
字串5
点击Next到下一步。
4) 设置包含这个Applet
网页
字串4
在这一步里,我们指定包含这个Applet网页
<applet>标签
一些属性,如下图所示:
字串7
图 6 设置引用Applet
网页 字串5
JBuilder会生成一个引用Applet
HTML网页,网页名字和Applet
类名相同,网页通过<applet>标签引用Applet,网页
标题及<applet>属性值在这一步中设置。
字串6
我们除将Height从默认
300调整为400,其他
都保持不变。按Next到最后一步。 字串4
5) 创建运行配置项 字串1
在这一步里JBuilder允许你决定是否为Applet生成一个运行配置项,运行配置项是允许你配置运行时
有关属性,如运行
入口类,在运行时是否重新编译等,你也可以通过Project->Project Properties...->Run来维护运行配置项。
图 7 设置Applet运行配置信息 字串8
点击Finish完成Applet
创建向导。此时JBuilder为这个Applet生成了两个文件,一个是TypeTrainApplet.java程序文件,而另一个是引用这个Applet
TypeTrainApplet.html网页。我们来看这两个文件
主要结构。 字串3
代码清单 1 TypeTrainApplet.html 引用Applet
网页表
1. <html>
2. <head>
3. <meta http-equiv=\"Content-Type\" content=\"text/html; charset=GBK\">
4. <title>
5. HTML Test Page
6. </title>
7. </head>
8. <body>
9. game.TypeTrainApplet will appear below in a Java enabled browser.<br>
10. <applet
11. codebase = \".\"
12. code = \"game.TypeTrainApplet.class\"
13. name = \"TestApplet\"
14. width = \"400\"
15. height = \"400\"
16. hspace = \"0\"
17. vspace = \"0\"
18. align = \"middle\"
19. >
20. <param name = \"stepLen\" value = \"2\">
21. <param name = \"stepInterval\" value = \"50\">
22. <param name = \"columnCount\" value = \"10\">
23. <param name = \"generateInterval\" value = \"500\">
24. </applet>
25. </body>
26. </html> 在向导第2步所设置
Applet参数悉数在网页中定义(第20~23行),在向导第3步中设置
Applet属性反映在第11~18行中。
字串3
Applet类
TypeTrainApplet.java文件代码如下所示:
代码清单 2 TypeTrainApplet.java
1. package game;
2.
3. import java.awt.*;
4. import java.awt.event.*;
5. import java.applet.*;
6. import javax.swing.*;
7.
8. public class TypeTrainApplet1 extends JApplet {
9. boolean isStandalone = false;
10. BorderLayout borderLayout1 = new BorderLayout();
11. int stepLen;
12. int stepInterval;
13. int columnCount;
14. int generateInterval;
15.
16. //Get a parameter value
17. public String getParameter(String key, String def) {
18. return isStandalone ? System.getProperty(key, def) :
19. (getParameter(key) != null ? getParameter(key) : def);
20. }
21.
22. //Construct the applet
23. public TypeTrainApplet1() {
24. }
25.
26. //Initialize the applet
27. public void init() {
28. try {
29. stepLen = Integer.parseInt(this.getParameter(\"stepLen\", \"2\"));
30. } catch (Exception e) {
31. e.printStackTrace();
32. }
33. try {
34. stepInterval = Integer.parseInt(this.getParameter(\"stepInterval\", 字串2
35. \"50\"));
36. } catch (Exception e) {
37. e.printStackTrace();
38. }
39. try {
40. columnCount = Integer.parseInt(this.getParameter(\"columnCount\",
41. \"10\"));
42. } catch (Exception e) {
43. e.printStackTrace();
44. }
45. try {
46. generateInterval = Integer.parseInt(this.getParameter(
47. \"generateInterval\", \"500\"));
48. } catch (Exception e) {
49. e.printStackTrace();
50. }
51. try {
52. jbInit();
53. } catch (Exception e) {
54. e.printStackTrace();
55. }
56. }
57.
58. //Component initialization
59. private void jbInit() throws Exception {
60. this.setSize(new Dimension(400, 300));
61. this.getContentPane().setLayout(borderLayout1);
62. }
63.
64. //Get Applet information
65. public String getAppletInfo() {
66. return \"Applet Information\";
67. }
68.
69. //Get parameter info 字串1
70. public String[][] getParameterInfo() {
71. java.lang.String[][] pinfo = { {
72. \"stepLen\", \"int\", \"每次下落
步长\"}, {
73. \"stepInterval\", \"int\", \"每移动一个像素
间隔时间,以毫秒为单位\"}, {
74. \"columnCount\", \"int\", 分成多少列\"}, {
75. \"generateInterval\", \"int\", 分成多少列\"},
76. };
77. return pinfo;
78. }
79.
80. //static initializer for setting look & feel
81. static {
82. try {
83. //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
84. } catch (Exception e) {
85. }
86. }
87. } 其中第11~14行定义了对应向导第2步所定义
参数变量,第70~78行获取参数
注释信息。在Applet通过init()初始化,在init()中调用方法将网页中参数
值赋给Applet类
成员变量,以初始化变量
值。在第59~62行设定了Applet
大小,其值应该和网页中<applet>
width和height属性值一致。
字串7
2、设计Applet界面
字串3
打开TypeTrainApplet.java,切换到Design视图页面中,设计如下
Applet界面
字串5
字串4
图 8 Applet界面设计 字串1
承继JApplet
Applet其默认
布局管理器是BorderLayout,首先在其东区(BorderLayout.EAST)放置一个infoPnl
JPanel组件,将infoPnl
布局管理器设置为GridLayout,9行1列,即在jbInit()方法中通过infoPnl.setLayout(new GridLayout(9, 1));设置。再在infoPnl上依次放置9个组件,这些组件
类型和用途分别说明如表所示: 字串9
表 2 组件说明
字串6
| 组件名 | 组件类型 | 用途 |
| jButton1 | JButton | 开始/暂停按钮 |
| jButton2 | JButton | 结束按钮 |
| jButton3 | JButton | 保存按钮 |
| totalLbl_1 | JLabel | 总数标签 |
| totalLbl_2 | JLabel | 总数值显示标签 |
| rightLbl_1 | JLabel | 正确数标签 |
| rightLbl_2 | JLabel | 正确数值显示标签 |
| errorLbl_1 | JLabel | 错误数标签 |
| errorLbl_2 | JLabel | 错误数值显示标签 |
你只要从设计器窗口左边
组件库中用鼠标将组件拖到设计窗口
相应位置,并放开鼠标就可以了相应生成用户界面
代码了。
字串4
由于画布组件没有java.awt.Canvas并没有列在JBuilder
组件面板中,你可以直接通过编码
方式把画布组件放到Applet
中区(BorderLayout.CENTER),了可以点击JBuilder可视化设计器
Bean选择器图标
(位于组件库
上方),在弹出
Bean Chooser对话框中选择java.awt.Canvas,如下图所示: 字串9
字串1
图 9 通过Bean选择器选择Canvas组件 字串6
在Bean Chooser对话框中有一棵以包组织
类树,选择Canvas类,再点击OK按钮,在可视化设计器
Bean选择器
下拉菜单中将出现java.awt.Canvas
类,如下图所示:
字串6
图 10 Bean选择器中
Canvas组件类
字串2
点击下拉菜单中
java.awt.Canvas,鼠标移到Applet设计界面
中心点击一下,一个画布组件就被添加到Applet
中区去了。在组件树中选中这个Applet中,将其命名为canvas,并确认其Constaints属性是CENTER(即位于中区)。 字串4
3、游戏
统计数据 字串7
游戏包括3个统计数据,即已产生字母
总数,被正确击中
字母数及未被击中
字母数。需要有3个变量来保存这些统计数据,同时还需要一个方法,将数据写到Applet界面
统计标签组件中去。当用户点击开始按钮时调用resetGame()方法将这些统计数据归0。 字串4
我们在TypeTrainApplet中添加以下粗体
代码。
字串7
代码清单 3 统计数据
字串9
1. …
2. public class TypeTrainApplet extends JApplet
3. {
4. …
5. volatile int totalCount = 0;//总数计数器
6. volatile int rightCount = 0;//正确数计数器
7. volatile int errorCount = 0;//错误数计数器
8. public TypeTrainApplet()
9. {}
10. …
11. //将统计结果画到界面上
12. private void drawResult()
13. {
14. totalLbl_2.setText(\"\" totalCount);
15. rightLbl_2.setText(\"\" rightCount);
16. errorLbl_2.setText(\"\" errorCount);
17. }
18. //重置现场
19. private void resetGame()
20. {
21. totalCount = 0;
22. rightCount = 0;
23. errorCount = 0;
24. drawResult();
25. }
26. …
27. }drawResult()方法以下两种情况下都应被调用:
字串9
·击中一个字母。 字串4
·一个字母下落到底端。 字串9
而resetGame()方法在点击开始按钮后调用,将3个统计变量归零,以便重新开始统计。
字串8
主体程序 字串6
1、字母下落线程
字串8
游戏界面中每一个下落
字母对应一个字母下落线程DropCharThread
实例,这个线程负责将一个随机
字母在指定
画布栏中从上至下落下。在TypeTrainApplet内部定义这个线程类,之所以要将其作为成员内部类来定义,是因为这样可以减少类和类之间
通信,降低调用接口
复杂度。DropCharThread需要访问到TypeTrainApplet
众多成员,作为内部类就可以直接访问TypeTrainApplet类
成员变量了。其代码如下所示:
字串6
代码清单 4 DropCharThread字母下落线程
字串7
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. private class DropCharThread extends Thread {
5. char c; //对应
字符
6. int colIndex; //在哪列下落
7. int x, y; //行列
坐标
8. private static final int ACTION_DRAW_FONT = 1; //画字符
9. private static final int ACTION_CLEAR_FONT = 2; //清字符
10. public DropCharThread(char c, int colIndex) {
11. this.c = c;
12. this.colIndex = colIndex;
13. this.x = (colIndex - 1) * colWidth colWidth / 2; //所在
横坐标
14. }
15. //线程方法
16. public void run() {
17. draw(ACTION_DRAW_FONT);
18. try {
19. while (c != pressKeyChar && y < canvas.getHeight() && statusCode != 0) {
20. synchronized (canvas) {
21. while (statusCode == 2) {
22. canvas.wait();
23. } 字串8
24. }
25. draw(ACTION_CLEAR_FONT);
26. y = stepLen;
27. draw(ACTION_DRAW_FONT);
28. Thread.sleep(stepInterval);
29. }
30. } catch (InterruptedException ex) {
31. }
32.
33. pressKeyChar = ' ';
34. draw(ACTION_CLEAR_FONT);
35. if (statusCode != 0) {//游戏没有停止
36. totalCount ; //统计总数
37. if (y < canvas.getHeight()) {
38. rightCount ; //击中
39. } else {
40. errorCount ; //打不中
41. }
42. drawResult();
43. }
44. }
45.
46. /**
47. * 画字母
48. * @param actionType 1:画字母 2: 清除字母
49. */
50. private void draw(int actionType) {
51. synchronized (canvas) { //必须对资源canvas进行同步,否则会产生线程不安全
52. Graphics g = canvas.getGraphics();
53. if (actionType == ACTION_CLEAR_FONT) {
54. g.setXORMode(canvas.getBackground()); //清除
55. }
56. g.setFont(new Font(\"Times New Roman\", Font.PLAIN, 12)); 字串3
57. g.drawString(\"\" c, x, y);
58. }
59. }
60. }
61. …
62. }由于这个类比较关键,逻辑也比较复杂,为了方便说明,我们将其流程通过一个流程图来描述,如下图所示: 字串4
字串9
图 11 字母下落线程流程图
1) 首先在栏序号为colIndex
栏
第一个位置画出保存在变量c中
字母(第17行)。
2) 当这个字母未被击中,未到达画布底部且用户未结束游戏进行循环,这步判断对应程序
19行。如果这个判断条件通过进入第3步,即进入循环体,否则转到第5步。
3) 如果被暂停,这个线程进入等待态,直接被通知后才继续运行。需要指明一点
是,所有字母下落线程都用画布对象canvas进行同步,即用canvas进行通讯。线程间要进行通讯时,一定需要通讯线程都可以访问到
对象充当媒介将这些线程\"串\"起来,通过这个对象
notify()/notifyAll()/wait()在线程间通讯。这个对象
比一个\"月下老人\",在线程
情人间传递音讯。
字串4
4) 当线程被唤醒后,或原来就没有等待,则进入下一个循环
处理过程,在这个过程中,程序将原来位置
字母清除,下移纵坐标,并在新
位置画字母,以达到字母下落
动画效果,然后下落线程睡眠指定
毫秒数,毫秒数值为TypeTrainApplet成员变量stepInterval
值,而这个值可以在网页
<param name = \"stepInterval\" value = \"50\">标签中定义,达到控制下落速度
效果。 字串2
因为在画布上画字母后,这个字母并不会自动消失,如果直接移动纵坐标并在新位置画字母,原位置
字母依就存在。所以在新位置画字母之前,必须先将旧位置
字母清除。我们用了一个小技巧,即使用Graphics对象
setXORMode()方法,该方法两图像重叠部分
颜色。我们调用这个方法将图像重叠部分
颜色设置为画布
背景色,这样在原来
位置上再次画字母时,因为前后两次画个字母刚
重叠,就达到了清除原位置字母
效果。 字串9
画字母和清除字母
程序相似,我们把它抽出到一个方法中draw(int actionType),如第50~59行代码所示,通过入参决定是清除还是画新字母。为增强程序
可读性,我们在第8~9行中定义了两个用于表示清字母和画字母
动作常量。 字串1
5) 当程序出了循环体后,进行善后
处理:将用于保存用户按键字母
pressKeyChar变量置为空字符,在画布上清除移到底部
字母。如果游戏没有结束统计数据,并将数据写到界面
JLabel组件中。
2、添加击中音效
字串6
击中字母后播放一个短促
声音,将能大大提高游戏
听觉体验,这在节里,我们对字母下落线程稍作更改,以使其支持音效。 字串7
首先准备一个声音文件hit.wav,放在TypeTrainApplet.java相同
文件夹下。Applet类中定义了一个getAudioClip(URL url)方法,通过这个方法可以获取AudioClip
声音文件
对象。通过AudioClip
play()即可播放这个音效。 字串7
代码清单 5
1. …
2. import java.applet.AudioClip;
3. public class TypeTrainApplet extends JApplet {
4. …
5. AudioClip hitSound;//声明音效对象
6. …
7. public void init() {
8. …
9. hitSound = getAudioClip( (TypeTrainApplet.class).getResource(
10. \"hit.wav\"));//初始化音效对象
11. }
12. …
13. private class DropCharThread extends Thread {
14. …
15. public void run() {
16. …
17. draw(ACTION_CLEAR_FONT);
18. if (statusCode != 0) { //游戏没有停止
19. totalCount ; //统计总数
20. if (y < canvas.getHeight()) {
21. hitSound.play();//击中时播放音效
22. rightCount ; //击中
23. } else {
24. errorCount ; //打不中
25. }
26. drawResult();
27. }
28. }
29. }
30. …
31. } 在第5行定义一个音效
对象,在Applet初始化时获取音效对象,如第9行所示。更改字母下落线程,当击中下落
字母时播放音效,如第21行所示。
字串3
3、字母下落线程
产生器线程 字串1
指法练习需要\"子子孙孙,无穷匮也\"地不断产生字母下落线程,以使游戏持续进行,这个工作由产生器线程GenerateDropThread负责。GenerateDropThread线程出于和DropCharThread同样
原因,也作为TypeTrainApplet成员内部类来定义,其代码如下所示:
字串6
代码清单 6 GenerateDropThread 产生器线程 字串2
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. private class GenerateDropThread extends Thread {
5. Random random = new Random(); //随机数
6. public void run() {
7. try {
8. while (statusCode != 0) { //产生下落线程
9. synchronized (canvas) {
10. while (statusCode == 2) {
11. canvas.wait();
12. }
13. }
14. DropCharThread dropCharThread = new DropCharThread(
15. getRandomChar(),
16. random.nextInt(columnCount) 1);
17. dropCharThread.start();
18. Thread.sleep(generateInterval);
19. }
20. } catch (InterruptedException ex) {
21. }
22. }
23.
24. /**
25. * <b>功能说明:</b><br>
26. * 返回一个随机字符
27. * @return 随机字符
28. */
29. private char getRandomChar() {
30. int temp = 97 random.nextInt(26);
31. return (char) temp; 字串2
32. }
33. } …
34. } 这个线程很简单:定期创建并启动一个DropCharThread字母下落线程。需要特别说明
是如何为字母下落线程提供一个随机字母和一个随机栏序号。我们通过一个随机对象java.util.Random
nextInt(int range)方法产生一个0~range-1
整数作为随机栏序号,在第29~32行定义了一个随机产生字母
getRandomChar()方法,因为小写字母a~z
ASCII代码是97~112,第30行即得到一个小写字母所对应
ASCII代码,通过第31行强制类型转换就可获取一个随机
小写字母字符。 字串1
在每次循环时,都判断游戏是否被暂停,如果暂停,则线程进入睡眠,暂停产生字母下落线程,如第8~13行所示。为了统一游戏总体
控制,所以这个线程也通过canvas对象进行同步,在其他地方调用canvas.notifyAll()方法后,暂停
线程就苏醒出来,继续工作。 字串3
在第18行,线程睡眠一小段时间,通过TypeTrainApplet
generateInterval成员变量就可以控制字母下落线程下落
速度,这个参数可以直接通过网页<param name = \"generateInterval\" value = \"500\">指定其值。 字串5
4、响应用户按键事件
所谓击中下落
字母,即是用户按下键盘中
一个键所对应
字母和某个字母下落线程
字母是一致
,对应
字母下落线程结束并将击中数递增1。 字串3
要让游戏自动监测到用户所按
按键,就需要Applet响应键盘按键事件,下面我们来为Applet生成按键事件
处理方法。
字串8
打开TypeTrainApplet.java,切换到Design视图页中,在结构窗格
组件树中选择this(BorderLayout)节点,切换属性查看器到Event标签页中,双击keyPressed项,如下图所示:
字串4
图 12 为Applet生成响应按键
事件处理方法
此时,JBuilder为Applet生成了一个按键事件监听器,并切换到Source视图页并将光标定位到事件处理方法中,在方法中键入如下粗体
代码。
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. /**获取用户点击按键所对应
字符*/
5. public void this_keyPressed(KeyEvent e) {
6. if (!e.isActionKey()) {
7. pressKeyChar = e.getKeyChar();
8. }
9. }
10. …
11. } 第6行判断按键是否字符
按键,如果是在第7行中获取按键所对应
字符。 字串8
控制游戏
至此,我们已经完成了Applet主要功能
开发,剩下
工作是如何通过按钮控制游戏。在编写控制代码之前,先为开始/暂停按钮(jButton1)和停止按钮(jButton2) 装饰一下,再编写控制代码。
字串1
1、为按钮添加图标
字串7
需要准备3张按钮
图标,图标为gif格式,尺寸大小为25×24象素。
字串8
·
:jButton1在结束和暂停状态
图标,命名为start.gif。 字串5
·
:jButton1在游戏处于运行状态
图标,命名为pause.gif。 字串5
·
:jButton2
图标,命名为stop.gif。当游戏处于暂停或运行状态时,jButton2才被激活。 字串8
将这些文件放置在TypeCharApplet.java源文件
目录下,即<工程根目录>/src/game目录下。
下面
代码使用java.awt.ImageIcon引用这3个图标,并在jbInit()中将图标显示到按钮上,如下所示:
字串5
代码清单 7 定义3个图标变量 字串6
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. ImageIcon startIcon = new ImageIcon(TypeTrainApplet.class.getResource(\"start.gif\"));
5. ImageIcon pauseIcon = new ImageIcon(TypeTrainApplet.class.getResource(\"pause.gif\"));
6. ImageIcon stopIcon = new ImageIcon(TypeTrainApplet.class.getResource(\"stop.gif\"));
7. …
8. private void jbInit() throws Exception {
9. …
10. jButton1.setIcon(startIcon);//设置开始按钮
图标
11. jButton2.setIcon(stopIcon);//设置停止按钮
图标
12. jButton2.setEnabled(false);//将停止按钮图标置为非激活态
13. …
14. }
15. } 第4~6用前面所述
图片初始化3个图标变量,其中TypeTrainApplet.class.getResource()方法以TypeTrainApplet.class所在目录为相对目录,查询资源文件。 字串8
第10~11行分别将开始和结束图标显示到对应
按钮上,当用户点击开始按钮后,才将jButton1
图标切换为暂停
图标pauseIcon。
字串1
2、通过按钮事件控制游戏 字串2
由于字母下落线程通过监测statusCode
值决定结束或暂停,所以我们仅需要通过按钮事件更改这个控制变量就可以达到控制游戏
目
了。
字串3
首先,我们打开TypeTrainApplet.java切换到Design
UI设计界面中,双击jButton1按钮,JBuilder自动为jButton1添加一个按钮点击事件监听器,并切换到Source视图中,将光标定位到事件处理方法处,我们在方法中添加以下粗体
代码: 字串5
代码清单 8 开始/暂停按钮事件处理方法 字串4
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. public void jButton1_actionPerformed(ActionEvent e) {
5. if (statusCode == 0) { //从结束->开始
6. resetGame();
7. statusCode = 1;
8. colWidth = canvas.getWidth() / columnCount;
9. //实例化字母下落线程产生器
10. GenerateDropThread gdThread = new GenerateDropThread();
11. gdThread.start();//产生器启动
12. jButton1.setIcon(pauseIcon);//切换为暂停
图标
13. jButton2.setEnabled(true);//停止按钮激活
14. } else if (statusCode == 1) { //从运行->暂停
15. statusCode = 2;
16. jButton1.setIcon(startIcon);
17. } else { //从暂停->运行
18. statusCode = 1;
19. jButton1.setIcon(pauseIcon);
20. synchronized (canvas) {//通过canvas通知所有暂停
线程继续运行
21. canvas.notifyAll();
22. }
23. }
24. this.requestFocus();//Applet接受光标,以便其接受按键事件 字串6
25. }
26. …
27. } 在jButton1
按钮点击事件处理方法里根据statusCode所标识
游戏状态分别进行处理:
·当statusCode=0时,游戏原处于结束或未开始
状态,表示用户执行开始游戏
命令。开始一个新游戏
命令,将统计数据归0,根据画布当前
宽度和栏数计算出每栏
宽度,实例化一个产生器线程,并切换按钮
图标为暂停图标,将停止按钮置为激活态。 字串8
·当statusCode=1时,游戏原处于运行态,表示用户执行暂停
命令。更改状态并更换按钮
图标。
字串1
·当statusCode=2时,游戏原处于暂停态,表示用户执行暂停后继续游戏
命令。更改状态并更换按钮图标,通过canvas对象通知所有暂停
线程。
其次,给停止按钮jButton2生成以下
事件响应代码:
代码清单 9 停止游戏
事件处理代码
字串3
1. …
2. public class TypeTrainApplet extends JApplet {
3. …
4. public void jButton2_actionPerformed(ActionEvent e) {
5. statusCode = 0;
6. synchronized (canvas) {
7. canvas.notifyAll();
8. }
9. jButton2.setEnabled(false);
10. jButton1.setIcon(startIcon);
11. }
12. …
13. } 首先更改游戏
状态,在第6~7行向所有处于等待状态
线程发出一个通知,防止线程\"睡死\"
情况。线程在循环体
判断语句中判断出statusCode为0后将纷纷退出,所有线程结束。而后,将按钮置为非激活状并将开始/暂停按钮切换为开始
图标。
3、保存游戏统计数据
为了演示通过数字签名技术突破Applet安全限制
方法,我们特地设计了一个功能:将游戏
统计数字写入到客户端机器
D:
esult.txt文件中。在UI设计界面中双击jButton3
按钮,为\"保存\"按钮添加如下
事件处理方法: 字串2
代码清单 10 保存按钮事件处理方法 字串8
1. …
2. import java.io.*;
3. public class TypeTrainApplet extends JApplet {
4. …
5. public void jButton3_actionPerformed(ActionEvent e) {
6. FileWriter fw = null;
7. try {
8. File file = new File(\"d:\result.txt\");
9. fw = new FileWriter(file);
10. fw.write(\"总数:\" totalCount \"
\");
11. fw.write(\"正确数:\" rightCount \"
\");
12. fw.write(\"失败数:\" errorCount);
13. fw.flush();
14. JOptionPane.showMessageDialog(this, \"成绩成功保存到d:
esult.txt中\",
15. \"信息\",JOptionPane.OK_OPTION);
16. } catch (IOException ex) {
17. ex.printStackTrace();
18. } finally {
19. try {
20. if (fw != null) {
21. fw.close();
22. }
23. } catch (IOException ex1) {
24. ex1.printStackTrace();
25. }
26. }
27. }
28. …
29. } 至此,我们就完成了整个游戏
开发过程,Rebuild事件工程,在<工程根目录>/classes文件夹下双击打开Applet向导为我们所生成
TypeTrainApplet.html网页,假如你机器已经安装了JRE,我们
指法练习游戏将在网页中打开,点击开始按钮玩伙自己亲手制作
游戏,如下图所示: 字串1
字串5
图 13 在网页中运行指法练习Applet游戏
字串1
点击停止按钮停止游戏,试着点击\"保存\"按钮,将统计数据保存到D: esult.txt中,你将会在Java控制台中看到一个安全异常信息,如下图所示:
字串1
字串6
图 14 Applet
功能被安全管理器限制
因为一般
Applet运行在称为\"沙盒\"
安全模块下,Applet虽然在客户端机器上运行,但至多只是一个\"外来客\",客户机没有将其当作\"自家人\"来对待。所以Applet不能执行访问本地文件系统、执行本地程序,保存统计数据到文件也就发生异常了。在本章后面,我们将详细介绍如何通过数字签名
技术来绕过Applet
安全限制,让客户机将这个\"外来客\"宾至如归。 字串8
4、关注Applet生命周期
Applet在浏览器中运行时,第一次加载Applet,将调用init()方法,接着调用start(),当窗口关闭或页面替换时先调用stop()然后再调用destroy()。
字串6
因为我们
游戏是多线程
程序,当关闭浏览器时,如果Applet
字母下落线程还在运行可能会引发异常。在JBuilder中右击TypeTrainApplet.html,在弹出
菜单中选择Run using default,JBuilder使用AppletViewer运行TypeTrainApplet。启动游戏后直接关闭窗口,在信息窗格中将报告以下
异常信息: 字串5
java.lang.NullPointerException
字串6
at game.TypeTrainApplet$DropCharThread.draw(TypeTrainApplet.java:290)
at game.TypeTrainApplet$DropCharThread.run(TypeTrainApplet.java:258) 字串9
这是由于关闭AppletViewer后,TypeTrainApplet画布
Graphics对象先被销毁,而字母下落线程依然调用访问这个对象,所以抛出空指针异常。 字串4
我们可以通过Applet
生命周期解决这个问题:Applet在被关闭前会调用stop()和destroy()方法。我们只要利用stop()方法就可以了,在stop()方法中置一个标识,线程通过判断这个标识就可以知道当前窗口是否关闭,当发现关闭时就不再运行。
1. public class TypeTrainApplet extends JApplet {
2. …
3. boolean isClose = false;//用于标识Applet窗口有没有关闭
4. …
5. public void start() {
6. isClose = false;
7. }
8.
9. public void stop() {
10. statusCode = 0;//停止游戏
11. isClose = true;//窗口关闭
12. }
13. …
14. private class DropCharThread extends Thread {
15. if(isClose) return ;//发现窗口关闭马上返回
16. draw(ACTION_DRAW_FONT);
17. try {
18. while (c != pressKeyChar && y < canvas.getHeight() &&
19. statusCode != 0) {
20. synchronized (canvas) {
21. while (statusCode == 2) {
22. canvas.wait();
23. }
24. }
25. draw(ACTION_CLEAR_FONT);
26. y = stepLen;
27. draw(ACTION_DRAW_FONT);
28. Thread.sleep(stepInterval);
29. }
30. } catch (InterruptedException ex) {
31. }
32. if (!isClose) {//窗口没有关闭才后续处理 字串1
33. draw(ACTION_CLEAR_FONT);
34. if (statusCode != 0) { //游戏没有停止
35. totalCount ; //统计总数
36. if (y < canvas.getHeight()) {
37. hitSound.play();
38. rightCount ; //击中
39. } else {
40. errorCount ; //打不中
41. }
42. drawResult();
43. }
44. }
45. }
46. } Applet启动时调用start()方法,这方法里将窗口关闭标识置为false,如第6行所示,而当窗口关闭时stop()方法被调用,停止游戏并置窗口关闭标识,如第10~11行所示。字母下落线程
程序也要作相应
调整,在进入线程和结束线程都判断是否关闭了窗口。
打包并进行数字签名 字串6
浏览器对Applet
数字签名支持并没有一个统一
标准,但是一些著名
浏览器如IE和Navigator对进行数字签名
Applet都可以开放大部分
权限。要对Applet进行数据签名必须先将Applet类和资源打成一个JAR包。
JBuilder提供一个Applet
打包向导,在向导
最后一步可以指定一个数据证书对最终生成
JAR包进行签名。所以在这一节里,我们先介绍数字签名
技术,而后再讲解如何使用JBuilder
Applet打包向导。 字串9
1、数字签名技术 字串8
数字签名涉及到以下几个基本
概念: 字串5
·消息摘要 字串2
消息摘要是对原始数据按照一定算法进行计算得到
结果,它主要检测原始数据是否被修改过。消息摘要与加密不同,加密是对原始数据进行变换,可以从变换后
数据中获得原始数据,而消息摘要是从原始数据中获得一部分信息,它比原始数据少得多,因此消息摘要可以看作是原始数据
指纹。
·消息验证码 字串9
当甲和乙通信时,甲将数据传给乙时,同时也将数据
消息摘要传给乙,乙收到后可以用该消息摘要验证甲传
消息是否正确。这时会产生问题,即若传递过程中别人修改了数据时,同时也修改了消息摘要。乙就无法确认数据是否正确。消息验证码可以解决这一问题。 使用消息验证码
前提是 甲和乙双方有一个共同
密钥,这样甲可以将数据计算出来
消息摘要加密后发给乙,以防止消息摘要被改。由于使用了共同
密钥,所以称为\"验证码\"。
·数字签名
使用消息摘要和消息验证码两种技术可以保证数据没有经过改变,但接收者还无法确定数据是否确实是某个人发来
。尽管消息码可以确定数据是某个有同样密钥
人发来
,但这要求双方具有共享
密钥,若有一组用户共享,我们就无法确定数据
来源了。 字串4
数字签名即是被设计用来解决这个问题
技术。数字签名利用非对称加密技术,发送者使用私钥加密数据产生
消息摘要(签名),接收者使用发送者
公钥解密消息摘要以验证签名是否是某个人
。由于私钥只有加密者才有,因此如果接收者用某个公钥解密了某个消息摘要,就可以确定这段消息摘要必然是对应
私钥持有者发来
。
字串3
·数字证书
使用数字签名
前提是接收数据者能够确信验证签名时(用发送者
私钥加密消息摘要)所用
公钥确实是发送者本人
,这需要通过数字证书来解决这个问题。
数字证书含有两部分数据:一部分是对应发送者(组织或个人)
信息,另一部分是这个发送者所对应
公钥。即数字证书保存了发送者和其公钥一一对应
关系。同样,数字证书也有可能被假造,有效
数字证书必须经过权威 CA
签名,即权威CA验证数字证书
内容
真实性,然后再在数字证书上使用权威CA自己
私钥签名,相当于在发送者
证书上盖章。 字串7
其实数字签名技术是现实生活在计算机领域
反映,我们不妨通过一个小故事将这此技术反向映射到生活中。 字串3
《永不消失
电波》是60年代一部著名
电影,讲述了1938年我党地下组织在国统区上海
电台被敌人破坏了,延安解放区我军电台政委李侠奉命前往
上海,加强秘密电台
工作,为了保证上海地下党组织能够正确接洽到真实
李侠而不被敌人蒙骗,我们不妨来设定这样
一个情节,李侠身上带一封介绍其身份
介绍信,这相当于消息摘要,还约定了接头暗号:地下党接头中说\"山上杜鹃红艳艳\",李侠则要接\"山下溪水细潺潺\",那么这个暗号就是\"消息验证码\"。而在李侠
介绍信上有延安电台台长
签名,这个就是\"数字签名\",签名之上还加盖了一个延安电台
公章,这个就是数字证书。还有一份证名电台公章
文件那就是CA证书了。当然实际情况可能只需要一个暗号,太多东西反而会在行动中暴露身份,但在计算机领域这些东西都是必要
。 字串3
2、数字证书
生成 字串4
在JBuilder
Applet打包向导中仅需要一个数字证书,向导会为最终
JAR包生成消息摘要、消息验证码并签名。通过JDK自带
Keytool工具可以为生成一个数据证书,这个工具位于JDK
bin目录下。
字串4
打开DOS命名窗口,定位到JBuilder 2005下自带
JDK
bin目录下,执行下面
Keytool命名生成一张自己
证书: 字串1
C:BorlandJBuilder2005jdk1.4in>keytool -genkey -alias chenxhCA -keyalg RSA -keystore superCALib -validity 3650
命令窗口将要求你输入一些个人信息如下图所示: 字串6
字串6
图 15 生成数字证书
命令窗口 字串2
这里我们使用keytool工具生成了一个名为chenxhCA
证书,它存放到superCALib证书库中,有效期为10年,使用
加密算法上RSA。证书库superCALib
访问密码是123456,而chenxhCA证书条目
访问密码是123123。在输入作为发送者身份标识
信息后就会在当前目标,即C:BorlandJBuilder2005jdk1.4in下生成一个名为superCALib
证书库文件。 字串2
keytool参数较多,使用也比较复杂,详细使用说明,请参见Sun网站
帮助文档:
http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html。 字串5
一般情况下你还需要将该证书发给权威
CA签名,这个证书才会被视为合法
证书,当然你也可以模拟创建一个CA证书,用这个CA证书为我们将用于签发Applet
chenxhCA证书签名,为了简单起见我们忽略这一步。 字串1
3、打包 字串5
现在已经万事俱备了,我们可以开始利用JBuilder
打包向导将Applet所以文件打包并签名
过程。 字串8
1) File->New...->Archive,在Archive页中双击Applet JAR图标启动Applet打包向导。 字串4
2) 在向导第1步中指定Applet JAR
名字和保存到目标文件,如下图所示: 字串5
图 16 指定文件名
为了加速网络下载速度,我们勾选上Compress the contents of the archive选项,压缩JAR文件,减小文件
体积。Always create archive when building the project选项使用每次编辑工程时都重新创建Applet JAR包。点击Next到下一步。
字串6
3) 在这一步里,指定JAR文件中所需包含
资源文件。
字串4
由于TypeTrainApplet程序引用了3张图片,所以JAR文件除包含TypeTrainApplet.class程序文件外,还需要将用于按钮图标
文件选择进来,如下图所示: 字串2
字串4
图 17 指定JAR
内容
字串3
按Next到下一步。 字串8
注意:
字串8
当你指定game.TypeTrainApplet.class,start.gif,pause.gif,stop.gif,hit.wav时,打成
Applet JAR包将不能正确运行,那些和TypeTrainApplet类位于同一程序文件
事件监听器类将被排除在外,所以需要通过game/*.*来打包。 字串6
4) 由于向导第3~6步,我们不需要作特别
设置,所以一直按Next到第7步。 字串5
在这一步里,我们用上一小节中生成
数字证书签名Applet
目标JAR文件,如下图所示:
字串6
字串3
图 18 指定如何对JAR进行签名 字串5
·Digitally sign this archive选项在默认
情况下是未选中
,首先勾选该选项
·点击Keystore后
…按钮,选择我们刚才在C:BorlandJBuilder2005jdk1.4in目录下所生成
superCALib证书库文件。
·在Keystore password中输入123456,即证书库
密码。 字串2
·点击Alias后
…按钮,由于我们在superCALib证书库中仅有一个chenxhca证书,所以在弹出
Select Alias对话框
Available Alias列表中仅有一个chenxhca选项,选择chenxhca证书。 字串6
·在Alias password中输入123123,即chenxhca证书
私钥密码。 字串8
·在Store type中输入JKS,由于Keytool工具
默认证书库类型是JKS,所以superCALib
类型为JKS。 字串3
在设置完以后
信息后,按Finish结束向导,在工程窗格
资源树中将出现一个TypeTrainJAR
节点。右击这个节点,在弹出
菜单中选择Rebuild,JBuilder将创建Applet
JAR包,并用chenxhca证书签名。 字串8
Rebuild完成后,工程窗格
TypeTrainJAR节点就可以展开了,展开这个节点,我们发现目标JAR文件中除了资源文件以外,在META-INF文件夹下还有3个文件,如下图所示:
字串3
图 19 目标JAR中关于签名
文件 字串7
META-INF文件夹下
3个文件是和数字签名有关
文件,说明如下: 字串7
·MANIFEST.MF:这个 manifest 文件定义了与扩展和包相关
数据。
字串3
·CHENXHCA.SF:这是 JAR 文件
签名文件,文件名标识了签名者。 字串7
·CHENXHCA.RSA:与签名文件相关联
签名程序块文件,它存储了用于签名 JAR 文件
公共签名。
4、在文件中引用Applet包文件 字串6
我们现在来更改TypeTrainApplet.html中<applet>
属性使其通过JAR来引用Applet程序。这个过程很简要,打开TypeTrainApplet.html文件,切换到Source视图页中,将光标定位在<applet>标签中。窗口右边出现<applet>标签
属性输入编辑器,在archive中输入game.JAR,按回车。
字串5
图 20 更改网页
<applet>标签属性
字串7
JBuilder为<applet>标签添加archive
属性。由于game.JAR文件位于工程根目录下,而TypeTrainApplet.html文件位于工程目录
classes子文件夹下,所以需要将TypeTrainApplet.html拷贝到工程根目录下,这样archiver=\"game.JAR\"
属性声明才是正确
,因为在寻找程序资源时,是以TypeTrainApplet.html所在目录为相对路径
。
保存后,到工程目录下双击TypeTrainApplet.html文件,IE检测到网页中包含了经过签名
Applet程序,弹出一个安全警告
对话框,如下图所示: 字串1
字串1
图 21 IE在运行签名
Applet前
安全警告
字串4
由于我们
证书没有经过权威机构
签名认证,所以对话框提示\"此安全证书是由不可信
公司签发
\"信息。需要指出
是游览器
JRE版本不同,弹出
警告对话框并不相同,上图是JRE版本为1.5.0时
警告对话框。 字串4
可以通过点击\"更多详细信息\"按钮查看证书
信息,如下图所示: 字串4
字串1
图 22 签名证书
信息
字串2
点选\"签发人\"项,将可以看到证书执有者
个人信息。关闭这个对话框,回到\"警告-安全\"对话框中,点击\"是\"接受这个签名
Applet。IE就对这个Applet开放了安全权限,不再受沙盒模型
限制了。
字串8
试着启动游戏,玩一伙儿后,点击\"保存\"按钮,Applet将正确地将统计数据保存到D: esult.txt文件中。
字串9
使用插件下载JRE
如果客户端游览器还未安装JRE或已安装
JRE版本低于你Applet
要求,或浏览器自带
JRE不是Sun公司标准
Applet,你Applet都可能无法正常运行。可以通过JDK自带
HtmlConverter.exe工具对带Applet
HTML文件进行转换,转换后
文件可以指定浏览器在运行Applet时将特定版本
JRE以插件
方式下载并安装,就象带Flash插件或SVG插件一样。
字串1
我们先从game工程根目录
classes目录下,拷贝TypeTrainApplet.html到game工程根目录下,以使其和game.jar位于同一个目录。 字串2
HtmlConverter.exe工具位于JDK
bin目录下,我们使用JDK5.0下
,导航到JDK5.0所安装
bin目录中,双击HtmlConverter.exe,稍等片刻,将弹出如下
对话框:
字串4
字串1
图 23 HTML转换工具 字串3
1.点击\"指定文件或目录路径\"后
\"浏览…\"按钮,选择工程目录下
TypeTrainApplet.html。
2.\"将文件备份到文件夹\"指定了将未转换前
TypeTrainApplet.html文件备份到
目录。 字串2
3.在\"模板文件\"中设置转换模板,根据你客户端用户所在
平台和使用
浏览器选择相应
选项。这里我们选择\"只适用Windows和Solaris
标准组件(IE和Navigator)\"。
字串1
4.点选\"使用任何Java1.5,或更高版本\",这样Java plug-in插件将使用JER1.5版本,这样将使用JRE1.5系统最新
版本,如果选择\"JRE1.5.0\"将保持插件版本不变,则不会去更新。 字串5
5.点击\"转换(C)…\"开始转换,原始
TypeTrainApplet.html被备份到备份文件夹下,在原位置
TypeTrainApplet.html已经被转换
结果覆盖。
提示:
如果你想使用JRE1.4或JRE1.3作为插件,则需要使用JDK1.4或JDK1.3所带
转换器进行转换。 字串5
打开转换后
TypeTrainApplet.html文件内容如下所示:
字串6
代码清单 11 转换后
TypeTrainApplet.html
字串4
1. <html>
2. <head>
3. <meta http-equiv=\"Content-Type\" content=\"text/html; charset=GBK\">
4. <title>HTML Test Page</title>
5. </head>
6. <body>game.TypeTrainApplet will appear below in a Java enabled browser.
7. <br>
8. <!--\"CONVERTED_APPLET\"-->
9. <!-- HTML CONVERTER -->
10. <object
11. classid = \"clsid:CAFEEFAC-0015-0000-0000-ABCDEFFEDCBA\"
12. codebase =
13. \"http://java.sun.com/update/1.5.0/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0\"
14. WIDTH = \"400\" HEIGHT = \"400\" NAME = \"TestApplet\" ALIGN = \"middle\" VSPACE =
15. \"0\" HSPACE = \"0\" >
16. <PARAM NAME = CODE VALUE = \"game.TypeTrainApplet.class\" >
17. <PARAM NAME = CODEBASE VALUE = \".\" >
18. <PARAM NAME = ARCHIVE VALUE = \"game.JAR\" >
19. <PARAM NAME = NAME VALUE = \"TestApplet\" >
20. <param name = \"type\" value = \"application/x-java-applet;jpi-version=1.5\">
21. <param name = \"scriptable\" value = \"false\">
22. <PARAM NAME = \"stepLen\" VALUE=\"2\"> 字串8
23. <PARAM NAME = \"stepInterval\" VALUE=\"50\">
24. <PARAM NAME = \"columnCount\" VALUE=\"10\">
25. <PARAM NAME = \"generateInterval\" VALUE=\"500\">
26.
27. <comment>
28. <embed
29. type = \"application/x-java-applet;jpi-version=1.5\"
30. CODE = \"game.TypeTrainApplet.class\"
31. JAVA_CODEBASE = \".\"
32. ARCHIVE = \"game.JAR\"
33. NAME = \"TestApplet\"
34. WIDTH = \"400\"
35. HEIGHT = \"400\"
36. ALIGN = \"middle\"
37. VSPACE = \"0\"
38. HSPACE = \"0\"
39. stepLen =\"2\"
40. stepInterval =\"50\"
41. columnCount =\"10\"
42. generateInterval =\"500\"
43. scriptable = false
44. pluginspage = \"http://java.sun.com/products/plugin/index.html#download\">
45. <noembed>
46.
47. </noembed>
48. </embed>
49. </comment>
50. </object>
51.
52. <!--
53. <APPLET CODE = \"game.TypeTrainApplet.class\" JAVA_CODEBASE = \".\" ARCHIVE
54. = \"game.JAR\" WIDTH = \"400\" HEIGHT = \"400\" NAME = \"TestApplet\" ALIGN = 字串4
55. \"middle\" VSPACE = \"0\" HSPACE = \"0\">
56. <PARAM NAME = \"stepLen\" VALUE=\"2\">
57. <PARAM NAME = \"stepInterval\" VALUE=\"50\">
58. <PARAM NAME = \"columnCount\" VALUE=\"10\">
59. <PARAM NAME = \"generateInterval\" VALUE=\"500\">
60. </APPLET>
61. -->
62. <!--\"END_CONVERTED_APPLET\"-->
63. </body>
64. </html> 第13行指定了下载JRE插件
地址,如果没有安装这样
版本,将自动下载当前 JRE 1.5 系列
缺省下载版本,如果不能自动安装,则将用户引导到下载页面中,用户可以手工下载JRE,下载页面在第44行指定。 字串5
如果你
Applet最终部署在一个Web服务器中,且Web服务器位于局域网中,则你事先可以将JRE1.5.0下载下来,放置到Web服务器
上下文中,并更改第13行和第44行
路径。
字串2
提示:
字串3
将jinstall-1_5_0-windows-i586.cab下载并放置到自己
Web服务器中,相应更改<object>
codebase属性值,并不会成功自动安装JRE1.5.0,因为jinstall-1_5_0-windows-i586.cab并未包含JRE1.5.0
安装程序,而是通过cab文件中
jinstall-1_5_0.inf文件声明根据http://java.sun.com/update/1.5.0/1.5.0-b64.xml
配置信息,从Sun网站下载后安装。如果你Web服务器所在
局域网不能直接访问Sun网站,安装过程将无法安成。你需要更改cab文件中
jinstall-1_5_0.inf文件,下载并更改1.5.0-b64.xml配置文件才可以使局域网
客户端到你自己
Web服务器指定地址下载。
字串4
如果Applet是在jsp而非html文件中调用,则可以使用<jsp:plugin>标签来引用applet,以使applet以插件方式引用JRE。关于<jsp:plugin>
使用方法,请查看jsp相关书籍。 字串5
总结 字串6
我们讲述了如何在JBuilder开发一个简单
Applet指法练习游戏程序
过程,虽然这个游戏在功能上属于不敢见公婆型,但它涵盖了Applet开发
大部分内容和技巧。我们特在Applet中设置了一个不安全
功能:在客户机器中保存文件,浏览器事先毫不留情地阻截了它,尔后我们通过数字签名技术晓之以情,动之以理\"说服\"了浏览器取消安全限制。
大千世界,纷繁复杂,客户端浏览器
JRE版本和厂家百家争鸣,百花齐放,为了使我们
Applet能够在Sun标准
JRE1.5.0
版本上运行,我们动用了JDK自带
转换器对原html进行转换,这样标准
JER1.5.0将作为插件
形式下载并安装以支持这个难伺候Applet。
字串6
![我要研发网[www.51dev.com]](/templets/images/toplogo.gif)
