友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第110部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
一个可以被用来在对象中调用相关方法的方法对象中产生。
通用方法列表包含了不相关的事件或者属性,例如 croak()。列表中所有的方法都是我们可以有计划的为
Bean 调用,并且应用程序构建工具可以选择列出所有的方法,当我们调用方法时,减轻我们的任务。
最后,我们可以看到事件在接收器中完全地分析研究它的方法、增加和减少接收器的方法。基本上,一旦我
们拥有BeanInfo ,我们就可以找出对Bean 来说任何重要的事物。我们同样可以为Bean 调用方法,即使我们
除了对象外没有任何其它的信息(此外,这也是映象的特点)。
462
…………………………………………………………Page 464……………………………………………………………
13。18。3 一个更复杂的 Bean
接下的程序例子稍微复杂一些,尽管这没有什么价值。这个程序是一张不论鼠标何时移动都围绕它画一个小
圆的 弧5蔽颐前聪率蟊昙 保 谄聊恢醒胂允疽桓鲎帧奥ang! ”,并且一个动作接收器被激活。画布。当
按下鼠标键时,我们可以改变的属性是圆的大小,除此之外还有被显示文字的色彩,大小,内容。BangBean
同样拥有它自己的addActionListener()和 removeActionListener()方法,因此我们可以附上自己的当用户
单击在BangBean 上时会被激活的接收器。这样,我们将能够确认可支持的属性和事件:
//: BangBean。java
// A graphical Bean
package bangbean;
import java。awt。*;
import java。awt。event。*;
import java。io。*;
import java。util。*;
public class BangBean extends Canvas
implements Serializable {
protected int xm; ym;
protected int cSize = 20; // Circle size
protected String text = 〃Bang!〃;
protected int fontSize = 48;
protected Color tColor = Color。red;
protected ActionListener actionListener;
public BangBean() {
addMouseListener(new ML());
addMouseMotionListener(new MML());
}
public int getCircleSize() { return cSize; }
public void setCircleSize(int newSize) {
cSize = newSize;
}
public String getBangText() { return text; }
public void setBangText(String newText) {
text = newText;
}
public int getFontSize() { return fontSize; }
public void setFontSize(int newSize) {
fontSize = newSize;
}
public Color getTextColor() { return tColor; }
public void setTextColor(Color newColor) {
tColor = newColor;
}
public void paint(Graphics g) {
g。setColor(Color。black);
g。drawOval(xm cSize/2; ym cSize/2;
cSize; cSize);
}
// This is a unicast listener; which is
// the simplest form of listener management:
public void addActionListener (
ActionListener l)
463
…………………………………………………………Page 465……………………………………………………………
throws TooManyListenersException {
if(actionListener != null)
throw new TooManyListenersException();
actionListener = l;
}
public void removeActionListener(
ActionListener l) {
actionListener = null;
}
class ML extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Graphics g = getGraphics();
g。setColor(tColor);
g。setFont(
new Font(
〃TimesRoman〃; Font。BOLD; fontSize));
int width =
g。getFontMetrics()。stringWidth(text);
g。drawString(text;
(getSize()。width width) /2;
getSize()。height/2);
g。dispose();
// Call the listener's method:
if(actionListener != null)
actionListener。actionPerformed(
new ActionEvent(BangBean。this;
ActionEvent。ACTION_PERFORMED; null));
}
}
class MML extends MouseMotionAdapter {
public void mouseMoved(MouseEvent e) {
xm = e。getX();
ym = e。getY();
repaint();
}
}
public Dimension getPreferredSize() {
return new Dimension(200; 200);
}
// Testing the BangBean:
public static void main(String'' args) {
BangBean bb = new BangBean();
try {
bb。addActionListener(new BBL());
} catch(TooManyListenersException e) {}
Frame aFrame = new Frame(〃BangBean Test〃);
aFrame。addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
});
464
…………………………………………………………Page 466……………………………………………………………
aFrame。add(bb; BorderLayout。CENTER);
aFrame。setSize(300;300);
aFrame。setVisible(true);
}
// During testing; send action information
// to the console:
static class BBL implements ActionListener {
public void actionPerformed(ActionEvent e) {
System。out。println(〃BangBean action〃);
}
}
} ///:~
最重要的是我们会注意到BangBean 执行了这种串联化的接口。这意味着应用程序构建工具可以在程序设计者
调整完属性值后利用串联为BangBean 贮藏所有的信息。当Bean 作为运行的应用程序的一部分被创建时,那
些被贮藏的属性被重新恢复,因此我们可以正确地得到我们的设计。
我们能看到通常同Bean 一起运行的所有的字段都是专用的——允许只能通过方法来访问,通常利用“属性”
结构。
当我们注视着addActionListener()的签名时,我们会注意到它可以产生出一个TooManyListenerException
(太多接收器异常)。这个异常指明它是一个单一的类型的,意味着当事件发生时,它只能通知一个接收
器。一般情况下,我们会使用具有多种类型的事件,以便一个事件通知多个的接收器。但是,那样会陷入直
到下一章我们才能准备好的结局中,因此这些内容会被重新回顾(下一个标题是“Java Beans 的重新回
顾”)。单一类型的事件回避了这个难题。
当我们按下鼠标键时,文字被安入 BangBean 中间,并且如果动作接收器字段存在,它的actionPerformed()
方法就被调用,创建一个新的ActionEvent 对象在处理过程中。无论何时鼠标移动,它的新座标将被捕捉,
并且画布会被重画(像我们所看到的抹去一些画布上的文字)。
main()方法增加了允许我们从命令行中测试程序的功能。当一个 Bean 在一个开发环境中,main()方法不会被
使用,但拥有它是绝对有益的,因为它提供了快捷的测试能力。无论何时一个ActionEvent 发生,main()方
法都将创建了一个帧并安置了一个 BangBean 在它里面,还在BangBean 中附上了一个简单的动作接收器以打
印到控制台。当然,一般来说应用程序构建工具将创建大多数的Bean 的代码。当我们通过BeanDumper 或者
安放BangBean 到一个可激活Bean 的开发环境中去运行BangBean 时,我们会注意到会有很多额外的属性和动
作明显超过了上面的代码。那是因为BangBean 从画布中继承,并且画布就是一个 Bean ,因此我们看到它的
属性和事件同样的合适。
13。18。4 Bean 的封装
在我们可以安放一个Bean 到一个可激活Bean 的可视化构建工具中前,它必须被放入到标准的Bean 容器里,
也就是包含 Bean 类和一个表示“这是一个Bean ”的清单文件的JAR (Java ARchive,Java 文件)文件中。
清单文件是一个简单的紧随事件结构的文本文件。对于BangBean 而言,清单文件就像下面这样:
Manifest…Version: 1。0
Name: bangbean/BangBean。class
Java…Bean: True
其中,第一行指出清单文件结构的版本,这是 SUN 公司在很久以前公布的版本。第二行(空行忽略)对文件
命名为BangBean。class。第三行表示“这个文件是一个Bean ”。没有第三行,程序构建工具不会将类作为一
个Bean 来认可。
唯一难以处理的部分是我们必须肯定“Name:”字段中的路径是正确的。如果我们回顾BangBean。java ,我们
会看到它在 package bangbean (因为存放类路径的子目录称为“bangbean ”)中,并且这个名字在清单文件
中必须包括封装的信息。另外,我们必须安放清单文件在我们封装路径的根目录上,在这个例子中意味着安
放文件在bangbean 子目录中。这之后,我们必须从同一目录中调用 Jar 来作为清单文件,如下所示:
jar cfm BangBean。jar BangBean。mf bangbean
465
…………………………………………………………Page 467……………………………………………………………
这个例子假定我们想产生一个名为 BangBean。jar 的文件并且我们将清单放到一个称为BangBean。mf 文件中。
我们可能会想“当我编译BangBean。java 时,产生的其它类会怎么样呢?”哦,它们会在bangbean 子目录中
被中止,并且我们会注意到上面jar命令行的最后一个自变量就是 bangbean 子目录。当我们给 jar子目录名
时,它封装整个的子目录到jar文件中(在这个例子中,包括 BangBean。java 的源代码文件——对于我们自
己的Bean 我们可能不会去选择包含源代码文件。)另外,如果我们改变主意,解开打包的 JAR 文件,我们会
发现我们清单文件并不在里面,但jar创建了它自己的清单文件(部分根据我们的文件),称为
MAINFEST。MF 并且安放它到META…INF子目录中(代表“meta…information”)。如果我们打开这个清单文
件,我们同样会注意到 jar为每个文件加入数字签名信息,其结构如下:
Digest…Algorithms: SHA MD5
SHA…Digest: pDpEAG9NaeCx8aFtqPI4udSX/O0=
MD5…Digest: O4NcS1hE3Smnzlp2hj6qeg==
一般来说,我们不必担心这些,如果我们要做一些修改,可以修改我们的原始的清单文件并且重新调用jar
以为我们的Bean 创建了一个新的JAR 文件。我们同样也可以简单地通过增加其它的 Bean 的信息到我们清单
文件来增加它们到 JAR 文件中。
值得注意的是我们或许需要安放每个Bean 到它自己的子目录中,因为当我们创建一个JAR 文件时,分配JAR
应用目录名并且JAR 放置子目录中的任何文件到JAR 文件中。我们可以看到 Frog 和 BangBean 都在它们自己
的子目录中。
一旦我们将我们的Bean 正确地放入一个 JAR 文件中,我们就可以携带它到一个可以激活Bean 的编程环境中
使用。使用这种方法,我们可以从一种工具到另一种工具间交替变换,但 SUN 公司为 Java Beans 提供了免费
高效的测试工具在它们的“Bean Development Kit,Bean 开发工具”(BDK)称为“beanbox”。(我们可以
从javasoft。 处下载。)在我们启动 beanbox 前,放置我们的Bean 到beanbox 中,复制JAR 文件到
BDK 的“jars”子目录中。
13。18。5 更复杂的 Bean 支持
我们可以看到创建一个 Bean 显然多么的简单。在程序设计中我们几乎不受到任何的限制。Java Bean 的设计
提供了一个简单的输入点,这样可以提高到更复杂的层次上。这些高层次的问题超出了这本书所要讨论的范
围,但它们会在此做简要的介绍。我们可以在 http://java。sun。/beans 上找到更多的详细资料。
我们增加更加复杂的程序和它的属性到一个位置。上面的例子显示一个独特的属性,当然它也可能代表一个
数组的属性。这称为索引属性。我们简单地提供一个相应的方法(再者有一个方法名的命名规则)并且
Introspector认可索引属性,因此我们的应用程序构建工具相应的处理。
属性可以被捆绑,这意味着它们将通过 PropertyChangeEvent 通知其它的对象。其它的对象可以随后根据对
Bean 的改变选择修改它们自己。
属性可以被束缚,这意味着其它的对象可以在一个属性的改变不能被接受时,拒绝它。其它的对象利用一个
PropertyChangeEvent 来通知,并且它们产生一个ProptertyVetoException 去阻止修改的发生,并恢复为原
来的值。
我们同样能够改变我们的Bean 在设计时的被描绘成的方法:
(1) 我们可以为我们特殊的 Bean 提供一个定制的属性表。这个普通的属性表将被所有的Bean 所使用,但当
我们的Bean 被选择时,它会自动地调用这张属性表。
(2) 我们可以为一个特殊的属性创建一个定制的编辑器,因此普通的属性表被使用,但当我们指定的属性被
调用时,编辑器会自动地被调用。
(3)我们可以为我们的 Bean 提供一个定制的BeanInfo 类,产生的信息不同于由 Introspector 默认产生的。
(4) 它同样可能在所有的FeatureDescriptors 中改变“expert”的开关模式,以辨别基本特征和更复杂的特
征。
13。18。6 Bean 更多的知识
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!