本文拟通过一个耳熟能详的指法练习游戏讲解如何在JBuilder 2005下开发Applet应用程序,通过本文,你将可以学习到图形用户界面开发、动画处理、声音播放、事件处理、多线程、I/O读写、Applet打包、Applet安全模型、数字签名、JRE插件制作、JDK5.0等方面的知识,并适时介绍笔者一些开发经验。
阅读导航:
指法练习Applet游戏介绍
我首先介绍一下这个游戏的界面,这个Applet共由11个组件组成,左边的主界面是画布Canvas组件,被分隔为10个栏。程序会随机在这些栏中产生下落的字母,用户按下匹配的字母键盘按键后,即为击中。
程序框架
打开JBuilder2005,创建一个工程(File->New...->Project->双击Project页中的Project图标),我们将工程名取为game,然后利用下面的步骤,调用Applet向导生成TypeTrainApplet。
主体程序
游戏界面中每一个下落的字母对应一个字母下落线程DropCharThread的实例,这个线程负责将一个随机的字母在指定的画布栏中从上至下落下。在TypeTrainApplet内部定义这个线程类,之所以要将其作为成员内部类来定义,是因为这样可以减少类和类之间的通信,降低调用接口的复杂度。
控制游戏
至此,我们已经完成了Applet主要功能的开发,剩下的工作是如何通过按钮控制游戏。在编写控制代码之前,先为开始/暂停按钮(jButton1)和停止按钮(jButton2) 装饰一下,再编写控制代码。
打包并进行数字签名
浏览器对Applet的数字签名支持并没有一个统一的标准,但是一些著名的浏览器如IE和Navigator对进行数字签名的Applet都可以开放大部分的权限。要对Applet进行数据签名必须先将Applet类和资源打成一个JAR包。
使用插件下载JRE
如果客户端游览器还未安装JRE或已安装的JRE版本低于你Applet的要求,或浏览器自带的JRE不是Sun公司标准的Applet,你Applet都可能无法正常运行。可以通过JDK自带的HtmlConverter.exe工具对带Applet的HTML文件进行转换。
总结
我们讲述了如何在JBuilder开发一个简单的Applet指法练习游戏程序的过程,虽然这个游戏在功能上属于不敢见公婆型,但它涵盖了Applet开发的大部分内容和技巧。我们特在Applet中设置了一个不安全的功能:在客户机器中保存文件,浏览器事先毫不留情地阻截了它,尔后我们通过数字签名技术晓之以情,动之以理"说服"了浏览器取消安全限制。
大千世界,纷繁复杂,客户端浏览器的JRE版本和厂家百家争鸣,百花齐放,为了使我们的Applet能够在Sun标准的JRE1.5.0的版本上运行,我们动用了JDK自带的转换器对原html进行转换,这样标准的JER1.5.0将作为插件的形式下载并安装以支持这个难伺候Applet。
指法练习Applet游戏介绍
1、界面及功能
指法练习的Applet游戏的界面如下图所示:
如上图所示,这个Applet共由11个组件组成,左边的主界面是画布Canvas组件,被分隔为10个栏。程序会随机在这些栏中产生下落的字母,用户按下匹配的字母键盘按键后,即为击中,相应的字母将消失,正确数递增1;字母落到画布底端后,还没有被击中,失败数递增1;每产生一个下落的字母,总数递增1。
游戏提供了3个JButton的按钮,分别用于控制游戏的开始/暂停、结束以及保存游戏成绩。在未启动游戏前第一个按钮显示为三角箭头的图标,点击后启动游戏,随后按钮图标切换为暂停的图标。而第二个为停止按钮,其上显示结束的图标,当游戏处于运行或暂停的状态时,点击该按钮将停止游戏以便重新开始。而第三个按钮保存游戏的成绩到客户端的D:/result.txt文件中。
整个界面采用BorderLayout布局管理器,画布位于BorderLayout.CENTER区,而右边的控制台JPanel位于BorderLayout.EAST区。控制台的JPanel采用GridLayout布局管理器。
2、程序组成
每个下落的字母对应一个线程实例,称为DropCharThread线程,它由一个产生器定时产生出来,这个产生器也是一个线程称为GenerateDropThread线程,下面是这个Applet的类图:
TypeTrainApplet类继承了JApplet,是游戏的主类,DropCharThread和GenerateDropThread都是其内部类,后两者都继承Thread,以线程的方式运行,下面对这3个类重要的成员变量和成员方法进行说明。
1).TypeTrainApplet
继承JApplet的Applet主类,负责构造用户界面、响应用户操作事件、更新游戏统计数据等。
· 重要成员变量
统计数据变量
这3个变量用volatile作了修饰,这是因为这3个变量会被每个字母下落线程更改,为防止各个线程通过各自的缓存更改变量值造成线程间值的不同步,需要将这3个变量设置为volatile的类型,这样这些变量的更改值对于其他线程马上可见。
字母下落速率控制变量
Applet通过通过这4个变量达到控制产生字母的快慢和字母下落的速度及栏数,可以进一步规划这些值,以形成游戏的难度级别。有鉴于此,我们特地将这些参数的值通过HTML的<Applet>参数传入。这样,只需要更改HTML的<applet>参数值就可以达到控制游戏难度级别的目标,而不需更改Applet程序。
其他
· 重要成员方法
2) DropCharThread
是一个线程,将一个随机的字母在画布的特定栏中往下落下,并实时检测是否被击中,如果击中马上消失,否则一直落到画布的底部。
·重要成员变量
·动作类型常量
不应当直接用1或2表示动作的类型,而应该定义一个更有意义的常量,这样不但于理解,也便于以后的维护。
·重要成员方法
3) GenerateDropThread
·重要成员变量
·重要成员方法
负责定时产生一个DropCharThread线程实例,通过generateInterval成员变量控制产生DropCharThread线程实例的频率。
当游戏玩家点击Applet的开始按钮后,Applet将启动游戏,这3个类之间的交互关系可以通过以下的顺序图来描述,如下图所示:
1)当用户按下Applet的开始按钮后激发一个事件。
2) Applet响应这个事件,调用事件响应方法,在方法中实例化一个GenerateDropThread线程,并启动这个线程。
3) GenerateDropThread线程定时产生一个DropCharThread线程,并让赋予一个随机的字母和栏序号。
4)DropCharThread线程启动,将字母在特定的栏中从上至下落下。
程序框架
1、利用向导生成Applet
首先创建一个工程(File->New...->Project->双击Project页中的Project图标),我们将工程名取为game,然后利用下面的步骤,调用Applet向导生成TypeTrainApplet。
1) 启动Applet向导
File->New...->Web->双击Web页中Applet的图标启动共4步的Applet向导。
2) 向导第1步,填写Applet的详细信息。
·ClassName:Applet的类名,填入TypeTrainApplet
·Package:包名,接受默认值
·Base Class:父类,有两个选项,一个是java.applet.Applet,另一个是javax.swing.JApplet。前者以AWT为基础,而后者以Swing为基础。如果客户端浏览器的JRE版本很低,且你不希望客户下载额外的插件,则需要考虑用java.applet.Applet,且不能应用高版本JDK中的特性,这里我们用javax.swing.JApplet。
·Generate header comments:在产生Applet代码时,产生类标题头的注释说明,你大可不必生成这些注释。
·Can run standalone:是否将Applet设置为可独立运行,如果勾选,JBuilder为其生成了一个main函数,这样就可以在脱离浏览器或AppletViewer的情况下,像一般可运行类一样运行这个Applet中的功能,我们不勾选它。
·Generate standard methods:是否生成Applet的标准函数,大家都知道Applet通过4个函数管理着Applet的生命周期,它们分别是init()、start()、stop()、destroy()。如果不勾选这个选项,向导只会生成init()方法,而其他3个方法不会生成。在我们的例子中,需要用到其他3个方法,所以需要勾选。
按Next到下一步。
3) 定义Applet的参数
Applet的参数是指通过网页中<applet>标签的<param>指定的参数值,这些值可以在Applet类中引用到。这样就允许在不改变Applet程序的情况下,仅通过网页中<applet>属性值的更改控制Applet的表现。我们在这一步中为Applet设置4个控制变量参数,如下图所示:
这一步的设置,不但为网页生成了参数声明,还为Applet程序生成了从网页获取参数值的方法,在Applet初始化时,即将网页中的参数值赋给Applet的成员变量。
点击Add Parameter新增一行,声明一个新的参数,其中Name*为网页中参数的名字,而Variable*为Applet类成员变量名,通过Type*栏设置成员变量的数据类型。你还可以为参数在Default栏中指定一个默认的值,在Desc中给出描述说明信息,其中带*的栏是必填的栏。
点击Next到下一步。
4) 设置包含这个Applet的网页
在这一步里,我们指定包含这个Applet网页的<applet>标签的一些属性,如下图所示:
JBuilder会生成一个引用Applet的HTML网页,网页名字和Applet的类名相同,网页通过<applet>标签引用Applet,网页的标题及<applet>属性值在这一步中设置。
我们除将Height从默认的300调整为400,其他的都保持不变。按Next到最后一步。
5) 创建运行配置项
在这一步里JBuilder允许你决定是否为Applet生成一个运行配置项,运行配置项是允许你配置运行时的有关属性,如运行的入口类,在运行时是否重新编译等,你也可以通过Project->Project Properties...->Run来维护运行配置项。
点击Finish完成Applet的创建向导。此时JBuilder为这个Applet生成了两个文件,一个是TypeTrainApplet.java程序文件,而另一个是引用这个Applet的TypeTrainApplet.html网页。我们来看这两个文件的主要结构。
代码清单 1 TypeTrainApplet.html 引用Applet的网页表
在向导第2步所设置的Applet参数悉数在网页中定义(第20~23行),在向导第3步中设置的Applet属性反映在第11~18行中。
Applet类的TypeTrainApplet.java文件代码如下所示:
代码清单 2 TypeTrainApplet.java
其中第11~14行定义了对应向导第2步所定义的参数变量,第70~78行获取参数的注释信息。在Applet通过init()初始化,在init()中调用方法将网页中参数的值赋给Applet类的成员变量,以初始化变量的值。在第59~62行设定了Applet的大小,其值应该和网页中<applet>的width和height属性值一致。
2、设计Applet界面
打开TypeTrainApplet.java,切换到Design视图页面中,设计如下的Applet界面
承继JApplet的Applet其默认的布局管理器是BorderLayout,首先在其东区(BorderLayout.EAST)放置一个infoPnl的JPanel组件,将infoPnl的布局管理器设置为GridLayout,9行1列,即在jbInit()方法中通过infoPnl.setLayout(new GridLayout(9, 1));设置。再在infoPnl上依次放置9个组件,这些组件的类型和用途分别说明如表所示:
表 2 组件说明
你只要从设计器窗口左边的组件库中用鼠标将组件拖到设计窗口的相应位置,并放开鼠标就可以了相应生成用户界面的代码了。
由于画布组件没有java.awt.Canvas并没有列在JBuilder的组件面板中,你可以直接通过编码的方式把画布组件放到Applet的中区(BorderLayout.CENTER),了可以点击JBuilder可视化设计器的Bean选择器图标 (位于组件库的上方),在弹出的Bean Chooser对话框中选择java.awt.Canvas,如下图所示:
在Bean Chooser对话框中有一棵以包组织的类树,选择Canvas类,再点击OK按钮,在可视化设计器的Bean选择器的下拉菜单中将出现java.awt.Canvas的类,如下图所示:
点击下拉菜单中的java.awt.Canvas,鼠标移到Applet设计界面的中心点击一下,一个画布组件就被添加到Applet的中区去了。在组件树中选中这个Applet中,将其命名为canvas,并确认其Constaints属性是CENTER(即位于中区)。
3、游戏的统计数据
游戏包括3个统计数据,即已产生字母的总数,被正确击中的字母数及未被击中的字母数。需要有3个变量来保存这些统计数据,同时还需要一个方法,将数据写到Applet界面的统计标签组件中去。当用户点击开始按钮时调用resetGame()方法将这些统计数据归0。
我们在TypeTrainApplet中添加以下粗体的代码。
代码清单 3 统计数据
drawResult()方法以下两种情况下都应被调用:
·击中一个字母。
·一个字母下落到底端。
而resetGame()方法在点击开始按钮后调用,将3个统计变量归零,以便重新开始统计。
阅读导航:
指法练习Applet游戏介绍
我首先介绍一下这个游戏的界面,这个Applet共由11个组件组成,左边的主界面是画布Canvas组件,被分隔为10个栏。程序会随机在这些栏中产生下落的字母,用户按下匹配的字母键盘按键后,即为击中。
程序框架
打开JBuilder2005,创建一个工程(File->New...->Project->双击Project页中的Project图标),我们将工程名取为game,然后利用下面的步骤,调用Applet向导生成TypeTrainApplet。
主体程序
游戏界面中每一个下落的字母对应一个字母下落线程DropCharThread的实例,这个线程负责将一个随机的字母在指定的画布栏中从上至下落下。在TypeTrainApplet内部定义这个线程类,之所以要将其作为成员内部类来定义,是因为这样可以减少类和类之间的通信,降低调用接口的复杂度。
控制游戏
至此,我们已经完成了Applet主要功能的开发,剩下的工作是如何通过按钮控制游戏。在编写控制代码之前,先为开始/暂停按钮(jButton1)和停止按钮(jButton2) 装饰一下,再编写控制代码。
打包并进行数字签名
浏览器对Applet的数字签名支持并没有一个统一的标准,但是一些著名的浏览器如IE和Navigator对进行数字签名的Applet都可以开放大部分的权限。要对Applet进行数据签名必须先将Applet类和资源打成一个JAR包。
使用插件下载JRE
如果客户端游览器还未安装JRE或已安装的JRE版本低于你Applet的要求,或浏览器自带的JRE不是Sun公司标准的Applet,你Applet都可能无法正常运行。可以通过JDK自带的HtmlConverter.exe工具对带Applet的HTML文件进行转换。
总结
我们讲述了如何在JBuilder开发一个简单的Applet指法练习游戏程序的过程,虽然这个游戏在功能上属于不敢见公婆型,但它涵盖了Applet开发的大部分内容和技巧。我们特在Applet中设置了一个不安全的功能:在客户机器中保存文件,浏览器事先毫不留情地阻截了它,尔后我们通过数字签名技术晓之以情,动之以理"说服"了浏览器取消安全限制。
大千世界,纷繁复杂,客户端浏览器的JRE版本和厂家百家争鸣,百花齐放,为了使我们的Applet能够在Sun标准的JRE1.5.0的版本上运行,我们动用了JDK自带的转换器对原html进行转换,这样标准的JER1.5.0将作为插件的形式下载并安装以支持这个难伺候Applet。
指法练习Applet游戏介绍
1、界面及功能
指法练习的Applet游戏的界面如下图所示:
图 1 指法练习的用户界面 |
如上图所示,这个Applet共由11个组件组成,左边的主界面是画布Canvas组件,被分隔为10个栏。程序会随机在这些栏中产生下落的字母,用户按下匹配的字母键盘按键后,即为击中,相应的字母将消失,正确数递增1;字母落到画布底端后,还没有被击中,失败数递增1;每产生一个下落的字母,总数递增1。
游戏提供了3个JButton的按钮,分别用于控制游戏的开始/暂停、结束以及保存游戏成绩。在未启动游戏前第一个按钮显示为三角箭头的图标,点击后启动游戏,随后按钮图标切换为暂停的图标。而第二个为停止按钮,其上显示结束的图标,当游戏处于运行或暂停的状态时,点击该按钮将停止游戏以便重新开始。而第三个按钮保存游戏的成绩到客户端的D:/result.txt文件中。
整个界面采用BorderLayout布局管理器,画布位于BorderLayout.CENTER区,而右边的控制台JPanel位于BorderLayout.EAST区。控制台的JPanel采用GridLayout布局管理器。
2、程序组成
每个下落的字母对应一个线程实例,称为DropCharThread线程,它由一个产生器定时产生出来,这个产生器也是一个线程称为GenerateDropThread线程,下面是这个Applet的类图:
图 2 Applet类图 |
TypeTrainApplet类继承了JApplet,是游戏的主类,DropCharThread和GenerateDropThread都是其内部类,后两者都继承Thread,以线程的方式运行,下面对这3个类重要的成员变量和成员方法进行说明。
1).TypeTrainApplet
继承JApplet的Applet主类,负责构造用户界面、响应用户操作事件、更新游戏统计数据等。
· 重要成员变量
统计数据变量
volatile int totalCount = 0;//生产下落字母的总数。 volatile int rightCount = 0;//正确击中的字母数。 volatile int errorCount = 0;//未被击中且到达画布底部的字母数。 |
这3个变量用volatile作了修饰,这是因为这3个变量会被每个字母下落线程更改,为防止各个线程通过各自的缓存更改变量值造成线程间值的不同步,需要将这3个变量设置为volatile的类型,这样这些变量的更改值对于其他线程马上可见。
字母下落速率控制变量
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程序。
其他
int colWidth; //下落字母每栏的宽度,在运行期才获取这个变量值,它由画布的宽度和栏数决定。 volatile char pressKeyChar; //记录当前按键对应的字母。 int statusCode = 0; //记录游戏所处的状态,其中1:运行态、,2:暂停态 0:停止态。 |
· 重要成员方法
private void drawResult()//将统计结果写到界面的对应JLabel中。 private void resetGame()//重置游戏现场 |
2) DropCharThread
是一个线程,将一个随机的字母在画布的特定栏中往下落下,并实时检测是否被击中,如果击中马上消失,否则一直落到画布的底部。
·重要成员变量
char c; //对应的字母 int colIndex; //对应画布的栏序号,第一栏为1,第二栏为2,以此类推 int x, y; //当前字母在画布中的坐标 |
·动作类型常量
private static final int ACTION_DRAW_FONT = 1; //表示画字符 private static final int ACTION_CLEAR_FONT = 2; //表示清除字符 |
不应当直接用1或2表示动作的类型,而应该定义一个更有意义的常量,这样不但于理解,也便于以后的维护。
·重要成员方法
public DropCharThread(char c, int colIndex)//构造函数,传入特定的字母和栏序号 private void draw(int actionType)//在画布中特写的位置上画字母 |
3) GenerateDropThread
·重要成员变量
Random random = new Random(); //负责产生随机数 |
·重要成员方法
private char getRandomChar()//获取一个随机的字母 |
负责定时产生一个DropCharThread线程实例,通过generateInterval成员变量控制产生DropCharThread线程实例的频率。
当游戏玩家点击Applet的开始按钮后,Applet将启动游戏,这3个类之间的交互关系可以通过以下的顺序图来描述,如下图所示:
图 3 开始游戏的顺序图 |
1)当用户按下Applet的开始按钮后激发一个事件。
2) Applet响应这个事件,调用事件响应方法,在方法中实例化一个GenerateDropThread线程,并启动这个线程。
3) GenerateDropThread线程定时产生一个DropCharThread线程,并让赋予一个随机的字母和栏序号。
4)DropCharThread线程启动,将字母在特定的栏中从上至下落下。
程序框架
1、利用向导生成Applet
首先创建一个工程(File->New...->Project->双击Project页中的Project图标),我们将工程名取为game,然后利用下面的步骤,调用Applet向导生成TypeTrainApplet。
1) 启动Applet向导
File->New...->Web->双击Web页中Applet的图标启动共4步的Applet向导。
2) 向导第1步,填写Applet的详细信息。
图 4 Applet向导第1步 |
·ClassName:Applet的类名,填入TypeTrainApplet
·Package:包名,接受默认值
·Base Class:父类,有两个选项,一个是java.applet.Applet,另一个是javax.swing.JApplet。前者以AWT为基础,而后者以Swing为基础。如果客户端浏览器的JRE版本很低,且你不希望客户下载额外的插件,则需要考虑用java.applet.Applet,且不能应用高版本JDK中的特性,这里我们用javax.swing.JApplet。
·Generate header comments:在产生Applet代码时,产生类标题头的注释说明,你大可不必生成这些注释。
·Can run standalone:是否将Applet设置为可独立运行,如果勾选,JBuilder为其生成了一个main函数,这样就可以在脱离浏览器或AppletViewer的情况下,像一般可运行类一样运行这个Applet中的功能,我们不勾选它。
·Generate standard methods:是否生成Applet的标准函数,大家都知道Applet通过4个函数管理着Applet的生命周期,它们分别是init()、start()、stop()、destroy()。如果不勾选这个选项,向导只会生成init()方法,而其他3个方法不会生成。在我们的例子中,需要用到其他3个方法,所以需要勾选。
按Next到下一步。
3) 定义Applet的参数
Applet的参数是指通过网页中<applet>标签的<param>指定的参数值,这些值可以在Applet类中引用到。这样就允许在不改变Applet程序的情况下,仅通过网页中<applet>属性值的更改控制Applet的表现。我们在这一步中为Applet设置4个控制变量参数,如下图所示:
图 5 为Applet设置参数 |
这一步的设置,不但为网页生成了参数声明,还为Applet程序生成了从网页获取参数值的方法,在Applet初始化时,即将网页中的参数值赋给Applet的成员变量。
点击Add Parameter新增一行,声明一个新的参数,其中Name*为网页中参数的名字,而Variable*为Applet类成员变量名,通过Type*栏设置成员变量的数据类型。你还可以为参数在Default栏中指定一个默认的值,在Desc中给出描述说明信息,其中带*的栏是必填的栏。
点击Next到下一步。
4) 设置包含这个Applet的网页
在这一步里,我们指定包含这个Applet网页的<applet>标签的一些属性,如下图所示:
图 6 设置引用Applet的网页 |
JBuilder会生成一个引用Applet的HTML网页,网页名字和Applet的类名相同,网页通过<applet>标签引用Applet,网页的标题及<applet>属性值在这一步中设置。
我们除将Height从默认的300调整为400,其他的都保持不变。按Next到最后一步。
5) 创建运行配置项
在这一步里JBuilder允许你决定是否为Applet生成一个运行配置项,运行配置项是允许你配置运行时的有关属性,如运行的入口类,在运行时是否重新编译等,你也可以通过Project->Project Properties...->Run来维护运行配置项。
图 7 设置Applet运行配置信息 |
点击Finish完成Applet的创建向导。此时JBuilder为这个Applet生成了两个文件,一个是TypeTrainApplet.java程序文件,而另一个是引用这个Applet的TypeTrainApplet.html网页。我们来看这两个文件的主要结构。
代码清单 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行中。
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", 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 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属性值一致。
2、设计Applet界面
打开TypeTrainApplet.java,切换到Design视图页面中,设计如下的Applet界面
图 8 Applet界面设计 |
承继JApplet的Applet其默认的布局管理器是BorderLayout,首先在其东区(BorderLayout.EAST)放置一个infoPnl的JPanel组件,将infoPnl的布局管理器设置为GridLayout,9行1列,即在jbInit()方法中通过infoPnl.setLayout(new GridLayout(9, 1));设置。再在infoPnl上依次放置9个组件,这些组件的类型和用途分别说明如表所示:
表 2 组件说明
组件名 | 组件类型 | 用途 |
jButton1 | JButton | 开始/暂停按钮 |
jButton2 | JButton | 结束按钮 |
jButton3 | JButton | 保存按钮 |
totalLbl_1 | JLabel | 总数标签 |
totalLbl_2 | JLabel | 总数值显示标签 |
rightLbl_1 | JLabel | 正确数标签 |
rightLbl_2 | JLabel | 正确数值显示标签 |
errorLbl_1 | JLabel | 错误数标签 |
errorLbl_2 | JLabel | 错误数值显示标签 |
你只要从设计器窗口左边的组件库中用鼠标将组件拖到设计窗口的相应位置,并放开鼠标就可以了相应生成用户界面的代码了。
由于画布组件没有java.awt.Canvas并没有列在JBuilder的组件面板中,你可以直接通过编码的方式把画布组件放到Applet的中区(BorderLayout.CENTER),了可以点击JBuilder可视化设计器的Bean选择器图标 (位于组件库的上方),在弹出的Bean Chooser对话框中选择java.awt.Canvas,如下图所示:
图 9 通过Bean选择器选择Canvas组件 |
在Bean Chooser对话框中有一棵以包组织的类树,选择Canvas类,再点击OK按钮,在可视化设计器的Bean选择器的下拉菜单中将出现java.awt.Canvas的类,如下图所示:
图 10 Bean选择器中的Canvas组件类 |
点击下拉菜单中的java.awt.Canvas,鼠标移到Applet设计界面的中心点击一下,一个画布组件就被添加到Applet的中区去了。在组件树中选中这个Applet中,将其命名为canvas,并确认其Constaints属性是CENTER(即位于中区)。
3、游戏的统计数据
游戏包括3个统计数据,即已产生字母的总数,被正确击中的字母数及未被击中的字母数。需要有3个变量来保存这些统计数据,同时还需要一个方法,将数据写到Applet界面的统计标签组件中去。当用户点击开始按钮时调用resetGame()方法将这些统计数据归0。
我们在TypeTrainApplet中添加以下粗体的代码。
代码清单 3 统计数据
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()方法以下两种情况下都应被调用:
·击中一个字母。
·一个字母下落到底端。
而resetGame()方法在点击开始按钮后调用,将3个统计变量归零,以便重新开始统计。