Serializable接口
首先,Bean必须实现Serializable接口。支持该接口的对象可通过磁盘保存和恢复它们的状态。已经定制的Bean(通常在构造工具中编辑其属性)必须能够在需要时保存和恢复自身的状态。为了实现Serializable接口,就要调入java.io.Serializable包,并且在类的定义中对你的 Bean 实现了Serializable进行说明。由于该Bean也是可见的,所以是从AWT组件java.awt.Canvas中扩展开来的。
Color 属性
Color属性是个私有的实例变量,其初始值为绿色:
private Color color = Color.green;
Get和Set方法
访问私有变量须通过get和set方法进行。注意:getter和setter方法的命名格式很特别,方法名以“get”或者“set”开始,后面跟的是属性名,而且属性名的第一个字母是大写的。(这个格式规定很重要,因为Bean的自检工具工作时就要用到这个规则)
这样,get和set方法的格式如下:
public <returntype> get<Propertyname>
public void set<Propertyname> (parameter)
对于SimpleBean的颜色属性,我们定义了下面的一对方法:
public Color getColor() { ... }
public void setColor(Color c) { ... }
测试和编辑Bean
这个Bean即将创建完毕,就要放到BeanBox中去了, 一旦完毕,它将会出现在ToolBox的组件栏目里。
把Bean放到BeanBox中去
首先,编译该Java源代码,之后,创建一个可执行的JAR文件,步骤如下:
编译该Bean的源代码,生成SimpleBean.class: javac SimpleBean.java
在文本编辑器中创建一个manifest(清单)文件。
manifest(清单)文件定义了类文件的名称,并指明这是个JavaBean。该manifest(清单)文件成为JAR 文件的一部分。你可以把manifest(清单)文件命名为manifest.tmp。该文件包含下列两行:
Name: SimpleBean.class
Java-Bean: True
(在Windows中,在manifest(清单) 文件中,务必包含在文本的结尾包含一个回车)
创建可执行的JAR文件。
使用jar命令,把manifest(清单)文件同SimpleBean.class文件联系起来:
(在一行中打入:)
jar cfm SimpleBean.jar manifest.tmp SimpleBean.class
在BeanBox的文件下拉菜单中,加载JAR文件到BeanBox中。 (教程的第一部分已经演示了这一步骤) 。从BeanBox的文件下拉菜单中,选择LoadJar, 就会出现文件浏览器。
找到SimpleBean.jar文件,选取它。注意:SimpleBean已经出现在ToolBox中Bean列表中。
把新的Bean放到BeanBox中,在TooBox中点击SimpleBean。 光标现在就变为十字状。
把光标移动到BeanBox内部的任何一处,再点击。SimpleBean就出现了,形状如下,红色矩形中有个小绿色矩阵。边界部分表明SimpleBean已经被选择,其属性出现在属性表中。
用鼠标拖动边界,你可以在BeanBox 中重新定位SimpleBean,一旦重新定位Bean时,光标就变为十字状箭头。因为SimpleBean是从Canvas中派生出来的,你可以重新改变其大小。只需要拖动其边界,就可以做到。
编辑Bean的属性
属性表显示出所选择的Bean的属性。SimpleBean具有下面四个属性:
· 颜色
· 背景
· 前景
· 名称
SimpleBean定义了颜色属性,其它三个属性是从Canvas中派生出来的。如果在诸如颜色这样的属性上点击,就会出现一个属性编辑器, 你可以改变属性的颜色值。对于诸如字体和颜色之类的属性,BeanBox提供了缺省的属性编辑器。
把其它属性添加到 Bean中也是很容易的。
把一个新属性声明为private变量。 可以在声明时就设定其初值,但这不是必需的。
声明一对公有的getter和setter方法,用于读取属性值,并设定新值。
记住:要对这些方法命名,规则是:名称前面为“get”和“set”,后面是变量的名称,而且第一个字母要大写。
如果你已经正确地为新属性定义了get和set方法,那么一旦Bean在BeanBox中被打开,你添加到Bean中的新属性就会出现在属性表中,通过自检机制, BeanBox就会找到同属性名相匹配的get和set 方法,并在属性表中显示出属性来。
下一步,我们将看看如何把其他种类的属性添加到Bean中,并且让Bean生成事件以及监听事件的发生。
JavaBeans和包
通常情况下,相对于其他Bean,不管是购自第三方还是你自己创建的Bean,应该安装在一个较为独立的目录中。Java的 packages(包)可以帮助你完成这个工作。 Java的包可以把相互关联的类组织在一起。
把Beans放到包中
把Bean放到包中,需要完成下列步骤:
在你文件的开始部分,加入包语句。包语句必须位于文件的第一行。
一个包语句定义了一个目录路径,该目录是用来存放编译后的Bean类文件的,其路径是相对于当前工作目录的,子目录是通过句点分隔的,而非斜杠。
例如,如果已编译过的Bean文件放在目录 \acme\Beans 中,就把下面一行加入到你的代码文件的开始部分:
package acme.Beans;
Acme03Bean是个带有颜色属性的简单的JavaBean, 它使用了包。本例中,你必须创建一个目录结构,以便Java编译器可以把所生成的类文件放到合适的位置。也要为放到包中的这些类文件定义包的名称。
一旦某个程序要使用包中的类,就要在程序中调入该包。
生成JAR文件时,要把包和类的全名都要包含进去,以便把属于包的Bean也包含进去。(JAR文件是Java Archive files的缩写。)对于那些由多个文件生成的Bean来说, JAR 文件是个理想的包装机制,JAR 文件既可以包含类文件,也可以同时包含图像文件。
在当前的工作目录下,为acme.Beans包创建合适的目录结构。首先创建两个单独的目录,一个用于Java源文件,另外一个用于Java类文件:
mkdir -p ./src/acme/Beans
mkdir -p ./classes/acme/Beans
把Java源文件拷到源目录中。在UNIX系统中:
cp -p Acme03Bean.java ./src/acme/Beans
当编译该JavaBean时,务必把编译好的类文件存放到类文件目录中,所以如果你使用makefile来进行编译,就要修改相应的makefile。
把标签添加到Beans中
在本课的这一节中,把一个实例变量加到AcmeBean中。该新的变量存放的是该Bean的String标签值。 (该Bean完整的源代码请见Acme04Bean )
添加标签
定义一个称为Label的私有变量:
private String label;
一旦定义好一个实例变量, 通过Bean的构造函数赋给它一个缺省值,同时设置修饰label的字体值。把如下两行添加到构造函数中去:
this.label="Bean"
setFont(new Font("Dialog"; Font.PLAIN, 12));
这样,该Bean就起到按钮的作用。你可以在构造工具(例如BeanBox工具)中对label进行设置。
如果打算在设计阶段能够设置label,让label成为Bean的一个属性,只要把get和set方法添加到Bean类中即可。
public String getLabel() {
return label;
}
public void setLabel(String newLabel) {
String oldLabel = label;
label = newLabel;
}
该方法同添加颜色属性时所要做的事情是类似的。
之后,通过在paint方法的最后加上如下几行代码,可以把按钮的效果做得更为逼真。 g.fillArc(5, 5, 30, 30, 0, 360);
g.fillArc(25, 5, 30, 30, 0, 360);
g.setColor(Color.blue);
int width = size().width;
int height = size().height;
FontMetrics fm = g.getFontMetrics();
g.drawString(label,
(width - fm.stringWidth(label)) / 2,
(height + fm.getMaxAscent() - fm.getMaxDescent())/ 2);
paint方法的定义如下:
public void paint(Graphics g) {
g.setColor(BeanColor);
g.fillRect(20,5,20,30);
g.fillArc(5,5,30,30,0,360);
g.fillArc(25,5,30,30,0,360);
g.setColor(Color.blue);
int width = size().width;
int height = size().height;
FontMetrics fm = g.getFontMetrics();
g.drawString(label,(width - fm.stringWidth(label))/2,
(height + fm.getMaxAscent() - fm.getMaxDescent())/2);
}