按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
〃Guarding is 〃 + safety'0'。getState());
else if(evt。target。equals(safety'1'))
t。setText(〃Hide the Ice Cream! 〃 +
〃Is it cold? 〃 + safety'1'。getState());
else
t。setText(arg。toString());
}
else
return super。action(evt; arg);
return true;
}
public static void main(String'' args) {
Menu1 f = new Menu1();
f。resize(300;200);
f。show();
}
} ///:~
在这个程序中,我避免了为每个菜单编写典型的冗长的add()列表调用,因为那看起来像许多的无用的标
志。取而代之的是,我安放菜单项到数组中,然后在一个 for 的循环中通过每个数组调用add()简单地跳
过。这样的话,增加和减少菜单项变得没那么讨厌了。
作为一个可选择的方法(我发现这很难令我满意,因为它需要更多的分配)CheckboxMenuItems 在数组的句
柄中被创建是被称为安全创建;这对数组文件和其它的文件而言是真正的安全。
程序中创建了不是一个而是二个的菜单条来证明菜单条在程序运行时能被交换激活。我们可以看到菜单条怎
样组成菜单,每个菜单怎样组成菜单项(MenuItems),chenkboxMenuItems 或者其它的菜单(产生子菜
单)。当菜单组合后,可以用setMenuBar()方法安装到现在的程序中。值得注意的是当按钮被压下时,它将
检查当前的菜单安装使用getMenuBar(),然后安放其它的菜单条在它的位置上。
当测试是“open”(即开始)时,注意拼写和大写,如果开始时没有对象,Java 发出no error (没有错误)
的信号。这种字符串比较是一个明显的程序设计错误源。
校验和非校验的菜单项自动地运行,与之相关的CheckBoxMenuItems 着实令人吃惊,这是因为一些原因它们
不允许字符串匹配。(这似乎是自相矛盾的,尽管字符串匹配并不是一种很好的办法。)因此,我们可以匹
403
…………………………………………………………Page 405……………………………………………………………
配一个目标对象而不是它们的标签。当演示时,getState()方法用来显示状态。我们同样可以用setState()
改变CheckboxMenuItem 的状态。
我们可能会认为一个菜单可以合理地置入超过一个的菜单条中。这看似合理,因为所有我们忽略的菜单条的
add()方法都是一个句柄。然而,如果我们试图这样做,这个结果将会变得非常的别扭,而远非我们所希望得
到的结果。(很难知道这是一个编程中的错误或者说是他们试图使它以这种方法去运行所产生的。)这个例
子同样向我们展示了为什么我们需要建立一个应用程序以替代程序片。(这是因为应用程序能支持菜单,而
程序片是不能直接使用菜单的。)我们从帧处继承代替从程序片处继承。另外,我们为类建一个构建器以取
代 init()安装事件。最后,我们创建一个main()方法并且在我们建的新型对象里,调整它的大小,然后调用
show()。它与程序片只在很小的地方有不同之处,然而这时它已经是一个独立的设置窗口应用程序并且我们
可以使用菜单。
13。15。2 对话框
对话框是一个从其它窗口弹出的窗口。它的目的是处理一些特殊的争议和它们的细节而不使原来的窗口陷入
混乱之中。对话框大量在设置窗口的编程环境中使用,但就像前面提到的一样,鲜于在程序片中使用。
我们需要从对话类处继承以创建其它类型的窗口、像帧一样的对话框。和窗框不同,对话框不能拥有菜单条
也不能改变光标,但除此之外它们十分的相似。一个对话框拥有布局管理器(默认的是BorderLayout 布局管
理器)和过载action()等等,或用 handleEvent() 去处理事件。我们会注意到handleEvent() 的一个重要差
异:当WINDOW_DESTORY 事件发生时,我们并不希望关闭正在运行的应用程序!
相反,我们可以使用对话窗口通过调用 dispace()释放资源。在下面的例子中,对话框是由定义在那儿作为
类的ToeButton 的特殊按钮组成的网格构成的(利用GridLayout 布局管理器)。ToeButton 按钮围绕它自已
画了一个帧,并且依赖它的状态:在空的中的“X”或者“O”。它从空白开始,然后依靠使用者的选择,
转换成“X”或“O”。但是,当我们单击在按钮上时,它会在“X”和“O”之间来回交换。(这产生了
一种类似填字游戏的感觉,当然比它更令人讨厌。)另外,这个对话框可以被设置为在主应用程序窗口中为
很多的行和列变更号码。
//: ToeTest。java
// Demonstration of dialog boxes
// and creating your own ponents
import java。awt。*;
class ToeButton extends Canvas {
int state = ToeDialog。BLANK;
ToeDialog parent;
ToeButton(ToeDialog parent) {
this。parent = parent;
}
public void paint(Graphics g) {
int x1 = 0;
int y1 = 0;
int x2 = size()。width 1;
int y2 = size()。height 1;
g。drawRect(x1; y1; x2; y2);
x1 = x2/4;
y1 = y2/4;
int wide = x2/2;
int high = y2/2;
if(state == ToeDialog。XX) {
g。drawLine(x1; y1; x1 + wide; y1 + high);
g。drawLine(x1; y1 + high; x1 + wide; y1);
}
if(state == ToeDialog。OO) {
g。drawOval(x1; y1; x1+wide/2; y1+high/2);
404
…………………………………………………………Page 406……………………………………………………………
}
}
public boolean
mouseDown(Event evt; int x; int y) {
if(state == ToeDialog。BLANK) {
state = parent。turn;
parent。turn= (parent。turn == ToeDialog。XX ?
ToeDialog。OO : ToeDialog。XX);
}
else
state = (state == ToeDialog。XX ?
ToeDialog。OO : ToeDialog。XX);
repaint();
return true;
}
}
class ToeDialog extends Dialog {
// w = number of cells wide
// h = number of cells high
static final int BLANK = 0;
static final int XX = 1;
static final int OO = 2;
int turn = XX; // Start with x's turn
public ToeDialog(Frame parent; int w; int h) {
super(parent; 〃The game itself〃; false);
setLayout(new GridLayout(w; h));
for(int i = 0; i 《 w * h; i++)
add(new ToeButton(this));
resize(w * 50; h * 50);
}
public boolean handleEvent(Event evt) {
if(evt。id == Event。WINDOW_DESTROY)
dispose();
else
return super。handleEvent(evt);
return true;
}
}
public class ToeTest extends Frame {
TextField rows = new TextField(〃3〃);
TextField cols = new TextField(〃3〃);
public ToeTest() {
setTitle(〃Toe Test〃);
Panel p = new Panel();
p。setLayout(new GridLayout(2;2));
p。add(new Label(〃Rows〃; Label。CENTER));
p。add(rows);
p。add(new Label(〃Columns〃; Label。CENTER));
p。add(cols);
add(〃North〃; p);
405
…………………………………………………………Page 407……………………………………………………………
add(〃South〃; new Button(〃go〃));
}
public boolean handleEvent(Event evt) {
if(evt。id == Event。WINDOW_DESTROY)
System。exit(0);
else
return super。handleEvent(evt);
return true;
}
public boolean action(Event evt; Object arg) {
if(arg。equals(〃go〃)) {
Dialog d = new ToeDialog(
this;
Integer。parseInt(rows。getText());
Integer。parseInt(cols。getText()));
d。show();
}
else
return super。action(evt; arg);
return true;
}
public stat ic void main(String'' args) {
Frame f = new ToeTest();
f。resize(200;100);
f。show();
}
} ///:~
ToeButton 类保留了一个句柄到它 ToeDialog 型的父类中。正如前面所述,ToeButton 和 ToeDialog 高度的结
合因为一个 ToeButton 只能被一个ToeDialog 所使用,但它却解决了一系列的问题,事实上这实在不是一个
糟糕的解决方案因为没有另外的可以记录用户选择的对话类。当然我们可以使用其它的制造ToeDialog。turn
(ToeButton 的静态的一部分)方法。这种方法消除了它们的紧密联系,但却阻止了我们一次拥有多个
ToeDialog (无论如何,至少有一个正常地运行)。
paint()是一种与图形有关的方法:它围绕按钮画出矩形并画出“X”或“O”。这完全是冗长的计算,但却
十分的直观。
一个鼠标单击被过载的 mouseDown()方法所俘获,最要紧的是检查是否有事件写在按钮上。如果没有,父窗
口会被询问以找出谁选择了它并用来确定按钮的状态。值得注意的是按钮随后交回到父类中并且改变它的选
择。如果按钮已经显示这为“X”和“O”,那么它们会被改变状态。我们能注意到本书第三章中描述的在
这些计算中方便的使用的三个一组的 If…else。当一个按钮的状态改变后,按钮会被重画。
ToeDialog 的构�