RSS
热门关键字:
当前位置 : 主页>编程开发>java编程>入门>列表

JBuilder 2005开发Applet游戏全接触

来源:我要研发网 作者: 时间:1970-01-01 点击:



  引言

  一张湘绣汇集了湘女累月心血,我们称之为劳动密集型,一块芯片集聚着众多高新科技,我们称之为技术密集型,一个实例承载了丰富知识点,是否可以称为知识密集型呢:)?用一张网捞到更多鱼是渔夫追求,通过一个实例学到更多知识点则是我们这些开发人员企盼。

字串7

  本文拟通过一个耳熟能详指法练习游戏讲解如何在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类图

字串5

  TypeTrainApplet类继承了JApplet,是游戏主类,DropCharThread和GenerateDropThread都是其内部类,后两者都继承Thread,以线程方式运行,下面对这3个类重要成员变量和成员方法进行说明。

字串3

  1).TypeTrainApplet 字串5

  继承JAppletApplet主类,负责构造用户界面、响应用户操作事件、更新游戏统计数据等。

字串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:停止态。

  · 重要成员方法

字串1

private void drawResult()//将统计结果写到界面对应JLabel中。
private void resetGame()//重置游戏现场

  2) DropCharThread 字串4

  是一个线程,将一个随机字母在画布特定栏中往下落下,并实时检测是否被击中,如果击中马上消失,否则一直落到画布底部。

字串2

  ·重要成员变量 字串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

  ·重要成员方法

字串4

public DropCharThread(char c, int colIndex)//构造函数,传入特定字母和栏序号
private void draw(int actionType)//在画布中特写位置上画字母

  3) GenerateDropThread 字串9

  ·重要成员变量 字串2

Random random = new Random(); //负责产生随机数

  ·重要成员方法

字串8

private char getRandomChar()//获取一个随机字母

  负责定时产生一个DropCharThread线程实例,通过generateInterval成员变量控制产生DropCharThread线程实例频率。 字串9

  当游戏玩家点击Applet开始按钮后,Applet将启动游戏,这3个类之间交互关系可以通过以下顺序图来描述,如下图所示: 字串3

   字串5

  图 3 开始游戏顺序图

字串8

  1)当用户按下Applet开始按钮后激发一个事件。

字串8

  2) Applet响应这个事件,调用事件响应方法,在方法中实例化一个GenerateDropThread线程,并启动这个线程。

字串7

  3) GenerateDropThread线程定时产生一个DropCharThread线程,并让赋予一个随机字母和栏序号。

字串5

  4)DropCharThread线程启动,将字母在特定栏中从上至下落下。 字串7

  程序框架

字串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个方法,所以需要勾选。

字串5

  按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到下一步。

字串3

  4) 设置包含这个Applet网页

字串4

  在这一步里,我们指定包含这个Applet网页<applet>标签一些属性,如下图所示:

字串7

  

字串3

  图 6 设置引用Applet网页 字串5

  JBuilder会生成一个引用AppletHTML网页,网页名字和Applet类名相同,网页通过<applet>标签引用Applet,网页标题及<applet>属性值在这一步中设置。

字串6

  我们除将Height从默认300调整为400,其他都保持不变。按Next到最后一步。 字串4

  5) 创建运行配置项 字串1

  在这一步里JBuilder允许你决定是否为Applet生成一个运行配置项,运行配置项是允许你配置运行时有关属性,如运行入口类,在运行时是否重新编译等,你也可以通过Project->Project Properties...->Run来维护运行配置项。

字串2

  

字串5

  图 7 设置Applet运行配置信息 字串8

  点击Finish完成Applet创建向导。此时JBuilder为这个Applet生成了两个文件,一个是TypeTrainApplet.java程序文件,而另一个是引用这个AppletTypeTrainApplet.html网页。我们来看这两个文件主要结构。 字串3

  代码清单 1 TypeTrainApplet.html 引用Applet网页表

字串1

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文件代码如下所示:

字串5

  代码清单 2 TypeTrainApplet.java

字串4

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

  承继JAppletApplet其默认布局管理器是BorderLayout,首先在其东区(BorderLayout.EAST)放置一个infoPnlJPanel组件,将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类,如下图所示:

字串1

   字串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 字母下落线程流程图

字串7

  1) 首先在栏序号为colIndex第一个位置画出保存在变量c中字母(第17行)。

字串9

  2) 当这个字母未被击中,未到达画布底部且用户未结束游戏进行循环,这步判断对应程序19行。如果这个判断条件通过进入第3步,即进入循环体,否则转到第5步。

字串1

  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组件中。

字串5

  2、添加击中音效

字串6

  击中字母后播放一个短促声音,将能大大提高游戏听觉体验,这在节里,我们对字母下落线程稍作更改,以使其支持音效。 字串7

  首先准备一个声音文件hit.wav,放在TypeTrainApplet.java相同文件夹下。Applet类中定义了一个getAudioClip(URL url)方法,通过这个方法可以获取AudioClip声音文件对象。通过AudioClipplay()即可播放这个音效。 字串7

  代码清单 5

字串8

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.RandomnextInt(int range)方法产生一个0~range-1整数作为随机栏序号,在第29~32行定义了一个随机产生字母getRandomChar()方法,因为小写字母a~zASCII代码是97~112,第30行即得到一个小写字母所对应ASCII代码,通过第31行强制类型转换就可获取一个随机小写字母字符。 字串1

  在每次循环时,都判断游戏是否被暂停,如果暂停,则线程进入睡眠,暂停产生字母下落线程,如第8~13行所示。为了统一游戏总体控制,所以这个线程也通过canvas对象进行同步,在其他地方调用canvas.notifyAll()方法后,暂停线程就苏醒出来,继续工作。  字串3

  在第18行,线程睡眠一小段时间,通过TypeTrainAppletgenerateInterval成员变量就可以控制字母下落线程下落速度,这个参数可以直接通过网页<param name = \"generateInterval\" value = \"500\">指定其值。 字串5

  4、响应用户按键事件

字串7

  所谓击中下落字母,即是用户按下键盘中一个键所对应字母和某个字母下落线程字母是一致,对应字母下落线程结束并将击中数递增1。 字串3

  要让游戏自动监测到用户所按按键,就需要Applet响应键盘按键事件,下面我们来为Applet生成按键事件处理方法。

字串8

  打开TypeTrainApplet.java,切换到Design视图页中,在结构窗格组件树中选择this(BorderLayout)节点,切换属性查看器到Event标签页中,双击keyPressed项,如下图所示:

字串8

   字串4

  图 12 为Applet生成响应按键事件处理方法

字串5

  此时,JBuilder为Applet生成了一个按键事件监听器,并切换到Source视图页并将光标定位到事件处理方法中,在方法中键入如下粗体代码。

字串1

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

  控制游戏

字串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目录下。

字串4

  下面代码使用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切换到DesignUI设计界面中,双击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所标识游戏状态分别进行处理:

字串1

  ·当statusCode=0时,游戏原处于结束或未开始状态,表示用户执行开始游戏命令。开始一个新游戏命令,将统计数据归0,根据画布当前宽度和栏数计算出每栏宽度,实例化一个产生器线程,并切换按钮图标为暂停图标,将停止按钮置为激活态。 字串8

  ·当statusCode=1时,游戏原处于运行态,表示用户执行暂停命令。更改状态并更换按钮图标。

字串1

  ·当statusCode=2时,游戏原处于暂停态,表示用户执行暂停后继续游戏命令。更改状态并更换按钮图标,通过canvas对象通知所有暂停线程。

字串1

  其次,给停止按钮jButton2生成以下事件响应代码:

字串6

  代码清单 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后将纷纷退出,所有线程结束。而后,将按钮置为非激活状并将开始/暂停按钮切换为开始图标。

字串6

  3、保存游戏统计数据

字串2

  为了演示通过数字签名技术突破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功能被安全管理器限制

字串1

  因为一般Applet运行在称为\"沙盒\"安全模块下,Applet虽然在客户端机器上运行,但至多只是一个\"外来客\",客户机没有将其当作\"自家人\"来对待。所以Applet不能执行访问本地文件系统、执行本地程序,保存统计数据到文件也就发生异常了。在本章后面,我们将详细介绍如何通过数字签名技术来绕过Applet安全限制,让客户机将这个\"外来客\"宾至如归。 字串8

  4、关注Applet生命周期

字串9

  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)

字串6

  at game.TypeTrainApplet$DropCharThread.run(TypeTrainApplet.java:258) 字串9

  这是由于关闭AppletViewer后,TypeTrainApplet画布Graphics对象先被销毁,而字母下落线程依然调用访问这个对象,所以抛出空指针异常。 字串4

  我们可以通过Applet生命周期解决这个问题:Applet在被关闭前会调用stop()和destroy()方法。我们只要利用stop()方法就可以了,在stop()方法中置一个标识,线程通过判断这个标识就可以知道当前窗口是否关闭,当发现关闭时就不再运行。

字串5

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行所示。字母下落线程程序也要作相应调整,在进入线程和结束线程都判断是否关闭了窗口。

字串9

  打包并进行数字签名 字串6

  浏览器对Applet数字签名支持并没有一个统一标准,但是一些著名浏览器如IE和Navigator对进行数字签名Applet都可以开放大部分权限。要对Applet进行数据签名必须先将Applet类和资源打成一个JAR包。

字串9

  JBuilder提供一个Applet打包向导,在向导最后一步可以指定一个数据证书对最终生成JAR包进行签名。所以在这一节里,我们先介绍数字签名技术,而后再讲解如何使用JBuilderApplet打包向导。 字串9

  1、数字签名技术 字串8

  数字签名涉及到以下几个基本概念: 字串5

  ·消息摘要 字串2

  消息摘要是对原始数据按照一定算法进行计算得到结果,它主要检测原始数据是否被修改过。消息摘要与加密不同,加密是对原始数据进行变换,可以从变换后数据中获得原始数据,而消息摘要是从原始数据中获得一部分信息,它比原始数据少得多,因此消息摘要可以看作是原始数据指纹。

字串8

  ·消息验证码 字串9

  当甲和乙通信时,甲将数据传给乙时,同时也将数据消息摘要传给乙,乙收到后可以用该消息摘要验证甲传消息是否正确。这时会产生问题,即若传递过程中别人修改了数据时,同时也修改了消息摘要。乙就无法确认数据是否正确。消息验证码可以解决这一问题。 使用消息验证码前提是 甲和乙双方有一个共同密钥,这样甲可以将数据计算出来消息摘要加密后发给乙,以防止消息摘要被改。由于使用了共同密钥,所以称为\"验证码\"。

字串9

  ·数字签名

字串7

  使用消息摘要和消息验证码两种技术可以保证数据没有经过改变,但接收者还无法确定数据是否确实是某个人发来。尽管消息码可以确定数据是某个有同样密钥人发来,但这要求双方具有共享密钥,若有一组用户共享,我们就无法确定数据来源了。 字串4

  数字签名即是被设计用来解决这个问题技术。数字签名利用非对称加密技术,发送者使用私钥加密数据产生消息摘要(签名),接收者使用发送者公钥解密消息摘要以验证签名是否是某个人。由于私钥只有加密者才有,因此如果接收者用某个公钥解密了某个消息摘要,就可以确定这段消息摘要必然是对应私钥持有者发来

字串3

  ·数字证书

字串7

  使用数字签名前提是接收数据者能够确信验证签名时(用发送者私钥加密消息摘要)所用公钥确实是发送者本人,这需要通过数字证书来解决这个问题。

字串7

  数字证书含有两部分数据:一部分是对应发送者(组织或个人)信息,另一部分是这个发送者所对应公钥。即数字证书保存了发送者和其公钥一一对应关系。同样,数字证书也有可能被假造,有效数字证书必须经过权威 CA签名,即权威CA验证数字证书内容真实性,然后再在数字证书上使用权威CA自己私钥签名,相当于在发送者证书上盖章。 字串7

  其实数字签名技术是现实生活在计算机领域反映,我们不妨通过一个小故事将这此技术反向映射到生活中。 字串3

  《永不消失电波》是60年代一部著名电影,讲述了1938年我党地下组织在国统区上海电台被敌人破坏了,延安解放区我军电台政委李侠奉命前往上海,加强秘密电台工作,为了保证上海地下党组织能够正确接洽到真实李侠而不被敌人蒙骗,我们不妨来设定这样一个情节,李侠身上带一封介绍其身份介绍信,这相当于消息摘要,还约定了接头暗号:地下党接头中说\"山上杜鹃红艳艳\",李侠则要接\"山下溪水细潺潺\",那么这个暗号就是\"消息验证码\"。而在李侠介绍信上有延安电台台长签名,这个就是\"数字签名\",签名之上还加盖了一个延安电台公章,这个就是数字证书。还有一份证名电台公章文件那就是CA证书了。当然实际情况可能只需要一个暗号,太多东西反而会在行动中暴露身份,但在计算机领域这些东西都是必要字串3

  2、数字证书生成 字串4

  在JBuilderApplet打包向导中仅需要一个数字证书,向导会为最终JAR包生成消息摘要、消息验证码并签名。通过JDK自带Keytool工具可以为生成一个数据证书,这个工具位于JDKbin目录下。

字串4

   打开DOS命名窗口,定位到JBuilder 2005下自带JDKbin目录下,执行下面Keytool命名生成一张自己证书: 字串1

  C:BorlandJBuilder2005jdk1.4in>keytool -genkey -alias chenxhCA -keyalg RSA -keystore superCALib -validity 3650

字串7

  命令窗口将要求你输入一些个人信息如下图所示: 字串6

   字串6

  图 15 生成数字证书命令窗口 字串2

  这里我们使用keytool工具生成了一个名为chenxhCA证书,它存放到superCALib证书库中,有效期为10年,使用加密算法上RSA。证书库superCALib访问密码是123456,而chenxhCA证书条目访问密码是123123。在输入作为发送者身份标识信息后就会在当前目标,即C:BorlandJBuilder2005jdk1.4in下生成一个名为superCALib证书库文件。 字串2

  keytool参数较多,使用也比较复杂,详细使用说明,请参见Sun网站帮助文档:

字串7

  http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html。 字串5

  一般情况下你还需要将该证书发给权威CA签名,这个证书才会被视为合法证书,当然你也可以模拟创建一个CA证书,用这个CA证书为我们将用于签发AppletchenxhCA证书签名,为了简单起见我们忽略这一步。 字串1

  3、打包 字串5

  现在已经万事俱备了,我们可以开始利用JBuilder打包向导将Applet所以文件打包并签名过程。 字串8

  1) File->New...->Archive,在Archive页中双击Applet JAR图标启动Applet打包向导。 字串4

  2) 在向导第1步中指定Applet JAR名字和保存到目标文件,如下图所示: 字串5

  

字串6

  图 16 指定文件名

字串3

  为了加速网络下载速度,我们勾选上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选项在默认情况下是未选中,首先勾选该选项

字串2

  ·点击Keystore后…按钮,选择我们刚才在C:BorlandJBuilder2005jdk1.4in目录下所生成superCALib证书库文件。

字串6

  ·在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将创建AppletJAR包,并用chenxhca证书签名。 字串8

  Rebuild完成后,工程窗格TypeTrainJAR节点就可以展开了,展开这个节点,我们发现目标JAR文件中除了资源文件以外,在META-INF文件夹下还有3个文件,如下图所示:

字串4

   字串3

  图 19 目标JAR中关于签名文件 字串7

  META-INF文件夹下3个文件是和数字签名有关文件,说明如下: 字串7

  ·MANIFEST.MF:这个 manifest 文件定义了与扩展和包相关数据。

字串3

  ·CHENXHCA.SF:这是 JAR 文件签名文件,文件名标识了签名者。 字串7

  ·CHENXHCA.RSA:与签名文件相关联签名程序块文件,它存储了用于签名 JAR 文件公共签名。

字串1

  4、在文件中引用Applet包文件 字串6

  我们现在来更改TypeTrainApplet.html中<applet>属性使其通过JAR来引用Applet程序。这个过程很简要,打开TypeTrainApplet.html文件,切换到Source视图页中,将光标定位在<applet>标签中。窗口右边出现<applet>标签属性输入编辑器,在archive中输入game.JAR,按回车。

字串2

   字串5

  图 20 更改网页<applet>标签属性

字串7

  JBuilder为<applet>标签添加archive属性。由于game.JAR文件位于工程根目录下,而TypeTrainApplet.html文件位于工程目录classes子文件夹下,所以需要将TypeTrainApplet.html拷贝到工程根目录下,这样archiver=\"game.JAR\"属性声明才是正确,因为在寻找程序资源时,是以TypeTrainApplet.html所在目录为相对路径

字串1

  保存后,到工程目录下双击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

字串4

  如果客户端游览器还未安装JRE或已安装JRE版本低于你Applet要求,或浏览器自带JRE不是Sun公司标准Applet,你Applet都可能无法正常运行。可以通过JDK自带HtmlConverter.exe工具对带AppletHTML文件进行转换,转换后文件可以指定浏览器在运行Applet时将特定版本JRE以插件方式下载并安装,就象带Flash插件或SVG插件一样。

字串1

  我们先从game工程根目录classes目录下,拷贝TypeTrainApplet.html到game工程根目录下,以使其和game.jar位于同一个目录。 字串2

  HtmlConverter.exe工具位于JDKbin目录下,我们使用JDK5.0下,导航到JDK5.0所安装bin目录中,双击HtmlConverter.exe,稍等片刻,将弹出如下对话框:

字串4

  

字串1

  图 23 HTML转换工具 字串3

  1.点击\"指定文件或目录路径\"后\"浏览…\"按钮,选择工程目录下TypeTrainApplet.html。

字串6

  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已经被转换结果覆盖。

字串8

  提示:

字串8

  如果你想使用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中设置了一个不安全功能:在客户机器中保存文件,浏览器事先毫不留情地阻截了它,尔后我们通过数字签名技术晓之以情,动之以理\"说服\"了浏览器取消安全限制。

字串4

  大千世界,纷繁复杂,客户端浏览器JRE版本和厂家百家争鸣,百花齐放,为了使我们Applet能够在Sun标准JRE1.5.0版本上运行,我们动用了JDK自带转换器对原html进行转换,这样标准JER1.5.0将作为插件形式下载并安装以支持这个难伺候Applet。

字串6

最新评论共有 2 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
相关文章