为留意到一些操作新事件模子的例子和为进修措施从老练新事件模子改变的要领,下面的例子回到在本章第一部门操作事件模子来证明的一些争议。别的,每个措施包罗措施片和应用措施此刻都可以借助或不借助欣赏器来运行。
1. 文本字段
这个例子同TextField1.java相似,但它增加了显然特另外行为:
//: TextNew.java
// Text fields with Java 1.1 events
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class TextNew extends Applet {
Button
b1 = new Button("Get Text"),
b2 = new Button("Set Text");
TextField
t1 = new TextField(30),
t2 = new TextField(30),
t3 = new TextField(30);
String s = new String();
public void init() {
b1.addActionListener(new B1());
b2.addActionListener(new B2());
t1.addTextListener(new T1());
t1.addActionListener(new T1A());
t1.addKeyListener(new T1K());
add(b1);
add(b2);
add(t1);
add(t2);
add(t3);
}
class T1 implements TextListener {
public void textValueChanged(TextEvent e) {
t2.setText(t1.getText());
}
}
class T1A implements ActionListener {
private int count = 0;
public void actionPerformed(ActionEvent e) {
t3.setText("t1 Action Event " + count++);
}
}
class T1K extends KeyAdapter {
public void keyTyped(KeyEvent e) {
String ts = t1.getText();
if(e.getKeyChar() ==
KeyEvent.VK_BACK_SPACE) {
// Ensure it's not empty:
if( ts.length() > 0) {
ts = ts.substring(0, ts.length() - 1);
t1.setText(ts);
}
}
else
t1.setText(
t1.getText() +
Character.toUpperCase(
e.getKeyChar()));
t1.setCaretPosition(
t1.getText().length());
// Stop regular character from appearing:
e.consume();
}
}
class B1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
s = t1.getSelectedText();
if(s.length() == 0) s = t1.getText();
t1.setEditable(true);
}
}
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
t1.setText("Inserted by Button 2: " + s);
t1.setEditable(false);
}
}
public static void main(String[] args) {
TextNew applet = new TextNew();
Frame aFrame = new Frame("TextNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
当TextField t1的行动吸收器被激活时,TextField t3就是一个需要陈诉的场合。我们留意到仅当我们按下“enter”键时,行动吸收器才会为“TextField”所激活。
TextField t1附有几个吸收器。T1吸收器从t1复制所有文字到t2,强制所有字符串转换成大写。我们会发明这两个事情同是举办的,而且假如我们增加T1K吸收器后我们再增加T1吸收器,它就不那么重要:在文字字段内的所有的字符串将一直被强制变为大写。这看起来键盘事件一直在文字组件事件前被激活,而且假如我们需要保存t2的字符串本来输入时的样子,我们就必需做一些出格的事情。
T1K有着其它的一些有趣的勾当。我们必需测试backspace(因为我们此刻节制着每一个事件)并执行删除。caret必需被明晰地配置到字段的末了;不然它不会像我们但愿的运行。最后,为了防备本来的字符串被默认的机制所处理惩罚,事件必需操作为事件工具而存在的consume()要领所“耗尽”。这会通知系统遏制激活其余非凡事件的事件处理惩罚器。
这个例子同样无声地证明白设计内部类的带来的诸多利益。留意下面的内部类:
class T1 implements TextListener {
public void textValueChanged(TextEvent e) {
t2.setText(t1.getText());
}
}
t1和t2不属于T1的一部门,而且到今朝为止它们都是很容易领略的,没有任何的非凡限制。这是因为一个内部类的工具能自动地捕获一个句柄到外部的建设它的工具哪里,因此我们可以处理惩罚封装类工具的要领和内容。正像我们看到的,这十分利便(注释⑥)。
⑥:它也办理了“回调”的问题,不必为Java插手任何令人恼火的“要领指针”特性。
2. 文本区域
Java 1.1版中Text Area最重要的改变就转动条。对付TextArea的构建器而言,我们可以当即节制TextArea是否会拥有转动条:程度的,垂直的,两者都有可能都没有。这个例子矫正了前面Java 1.0版TextArea1.java措施片,演示了Java 1.1版的转动条构建器:
//: TextAreaNew.java
// Controlling scrollbars with the TextArea
// component in Java 1.1
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class TextAreaNew extends Applet {
Button b1 = new Button("Text Area 1");
Button b2 = new Button("Text Area 2");
Button b3 = new Button("Replace Text");
Button b4 = new Button("Insert Text");
TextArea t1 = new TextArea("t1", 1, 30);
TextArea t2 = new TextArea("t2", 4, 30);
TextArea t3 = new TextArea("t3", 1, 30,
TextArea.SCROLLBARS_NONE);
TextArea t4 = new TextArea("t4", 10, 10,
TextArea.SCROLLBARS_VERTICAL_ONLY);
TextArea t5 = new TextArea("t5", 4, 30,
TextArea.SCROLLBARS_HORIZONTAL_ONLY);
TextArea t6 = new TextArea("t6", 10, 10,
TextArea.SCROLLBARS_BOTH);
public void init() {
b1.addActionListener(new B1L());
add(b1);
add(t1);
b2.addActionListener(new B2L());
add(b2);
add(t2);
b3.addActionListener(new B3L());
add(b3);
b4.addActionListener(new B4L());
add(b4);
add(t3); add(t4); add(t5); add(t6);
}
class B1L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t5.append(t1.getText() + "\n");
}
}
class B2L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t2.setText("Inserted by Button 2");
t2.append(": " + t1.getText());
t5.append(t2.getText() + "\n");
}
}
class B3L implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s = " Replacement ";
t2.replaceRange(s, 3, 3 + s.length());
}
}
class B4L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t2.insert(" Inserted ", 10);
}
}
public static void main(String[] args) {
TextAreaNew applet = new TextAreaNew();
Frame aFrame = new Frame("TextAreaNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,725);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
#p#分页标题#e#
我们发明只能在结构TextArea时可以或许节制转动条。同样,纵然TE AR没有转动条,我们转动光标也将被避免(可通过运行这个例子中验证这种行为)。
3. 复选框和单选钮
正如早先指出的那样,复选框和单选钮都是同一个类成立的。单选钮和复选框略有差异,它是复选框安放到CheckboxGroup中组成的。在个中任一种环境下,有趣的ItemEvent事件为我们建设一个ItemListener项目吸收器。
当处理惩罚一组复选框可能单选钮时,我们有一个不错的选择。我们可以建设一个新的内部类去为每个复选框处理惩罚事件,可能建设一个内部类判定哪个复选框被单击并注册一个内部类单独的工具为每个复选工具。下面的例子演示了两种要领:
//: RadioCheckNew.java
// Radio buttons and Check Boxes in Java 1.1
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class RadioCheckNew extends Applet {
TextField t = new TextField(30);
Checkbox[] cb = {
new Checkbox("Check Box 1"),
new Checkbox("Check Box 2"),
new Checkbox("Check Box 3") };
CheckboxGroup g = new CheckboxGroup();
Checkbox
cb4 = new Checkbox("four", g, false),
cb5 = new Checkbox("five", g, true),
cb6 = new Checkbox("six", g, false);
public void init() {
t.setEditable(false);
add(t);
ILCheck il = new ILCheck();
for(int i = 0; i < cb.length; i++) {
cb[i].addItemListener(il);
add(cb[i]);
}
cb4.addItemListener(new IL4());
cb5.addItemListener(new IL5());
cb6.addItemListener(new IL6());
add(cb4); add(cb5); add(cb6);
}
// Checking the source:
class ILCheck implements ItemListener {
public void itemStateChanged(ItemEvent e) {
for(int i = 0; i < cb.length; i++) {
if(e.getSource().equals(cb[i])) {
t.setText("Check box " + (i + 1));
return;
}
}
}
}
// vs. an individual class for each item:
class IL4 implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("Radio button four");
}
}
class IL5 implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("Radio button five");
}
}
class IL6 implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("Radio button six");
}
}
public static void main(String[] args) {
RadioCheckNew applet = new RadioCheckNew();
Frame aFrame = new Frame("RadioCheckNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
#p#分页标题#e#
ILCheck拥有当我们增加可能淘汰复选框时自动调解的利益。虽然,我们对单选钮利用这种要领也同样的好。可是,它仅当我们的逻辑足以普遍的支持这种要领时才会被利用。假如声明一个确定的信号——我们将反复操作独立的吸收器类,不然我们将竣事一串条件语句。
4. 下拉列表
下拉列表在Java 1.1版中当一个选择被改变时同样利用ItemListener去奉告我们:
//: ChoiceNew.java
// Drop-down lists with Java 1.1
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class ChoiceNew extends Applet {
String[] description = { "Ebullient", "Obtuse",
"Recalcitrant", "Brilliant", "Somnescent",
"Timorous", "Florid", "Putrescent" };
TextField t = new TextField(100);
Choice c = new Choice();
Button b = new Button("Add items");
int count = 0;
public void init() {
t.setEditable(false);
for(int i = 0; i < 4; i++)
c.addItem(description[count++]);
add(t);
add(c);
add(b);
c.addItemListener(new CL());
b.addActionListener(new BL());
}
class CL implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("index: " + c.getSelectedIndex()
+ " " + e.toString());
}
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(count < description.length)
c.addItem(description[count++]);
}
}
public static void main(String[] args) {
ChoiceNew applet = new ChoiceNew();
Frame aFrame = new Frame("ChoiceNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(750,100);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
这个措施中没什么出格新颖的对象(除了Java 1.1版的UI类里少数几个值得存眷的缺陷)。
5. 列表
我们消除了Java 1.0中List设计的一个缺陷,就是List不能像我们但愿的那样事情:它会与单击在一个列表元素上产生斗嘴。
//: ListNew.java
// Java 1.1 Lists are easier to use
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class ListNew extends Applet {
String[] flavors = { "Chocolate", "Strawberry",
"Vanilla Fudge Swirl", "Mint Chip",
"Mocha Almond Fudge", "Rum Raisin",
"Praline Cream", "Mud Pie" };
// Show 6 items, allow multiple selection:
List lst = new List(6, true);
TextArea t = new TextArea(flavors.length, 30);
Button b = new Button("test");
int count = 0;
public void init() {
t.setEditable(false);
for(int i = 0; i < 4; i++)
lst.addItem(flavors[count++]);
add(t);
add(lst);
add(b);
lst.addItemListener(new LL());
b.addActionListener(new BL());
}
class LL implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("");
String[] items = lst.getSelectedItems();
for(int i = 0; i < items.length; i++)
t.append(items[i] + "\n");
}
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(count < flavors.length)
lst.addItem(flavors[count++], 0);
}
}
public static void main(String[] args) {
ListNew applet = new ListNew();
Frame aFrame = new Frame("ListNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
我们可以留意到在列表项中无需出格的逻辑需要去支持一个单击行动。我们正仿佛我们在其它处所所做的那样附加上一个吸收器。
6. 菜单
为菜单处理惩罚事件看起来受益于Java 1.1版的事件模子,但Java生成菜单的要领经常贫苦而且需要一些手工编写代码。生成菜单的正确要领看起来像资源而不是一些代码。请牢紧记着编程东西会遍及地为我们处理惩罚建设的菜单,因此这可以淘汰我们的疾苦(只要它们会同样处理惩罚维护任务!)。别的,我们将发明菜单不支持而且将导致杂乱的事件:菜单项利用ActionListeners(行动吸收器),但复选框菜单项利用ItemListeners(项目吸收器)。菜单工具同样能支持ActionListeners(行动吸收器),但凡是不那么有用。一般来说,我们会附加吸收器到每个菜单项或复选框菜单项,但下面的例子(对先前例子的修改)演示了一个连系捕获多个菜单组件到一个单独的吸收器类的要领。正像我们将看到的,它或者不值得为这而剧烈地争论。
//: MenuNew.java
// Menus in Java 1.1
import java.awt.*;
import java.awt.event.*;
public class MenuNew extends Frame {
String[] flavors = { "Chocolate", "Strawberry",
"Vanilla Fudge Swirl", "Mint Chip",
"Mocha Almond Fudge", "Rum Raisin",
"Praline Cream", "Mud Pie" };
TextField t = new TextField("No flavor", 30);
MenuBar mb1 = new MenuBar();
Menu f = new Menu("File");
Menu m = new Menu("Flavors");
Menu s = new Menu("Safety");
// Alternative approach:
CheckboxMenuItem[] safety = {
new CheckboxMenuItem("Guard"),
new CheckboxMenuItem("Hide")
};
MenuItem[] file = {
// No menu shortcut:
new MenuItem("Open"),
// Adding a menu shortcut is very simple:
new MenuItem("Exit",
new MenuShortcut(KeyEvent.VK_E))
};
// A second menu bar to swap to:
MenuBar mb2 = new MenuBar();
Menu fooBar = new Menu("fooBar");
MenuItem[] other = {
new MenuItem("Foo"),
new MenuItem("Bar"),
new MenuItem("Baz"),
};
// Initialization code:
{
ML ml = new ML();
CMIL cmil = new CMIL();
safety[0].setActionCommand("Guard");
safety[0].addItemListener(cmil);
safety[1].setActionCommand("Hide");
safety[1].addItemListener(cmil);
file[0].setActionCommand("Open");
file[0].addActionListener(ml);
file[1].setActionCommand("Exit");
file[1].addActionListener(ml);
other[0].addActionListener(new FooL());
other[1].addActionListener(new BarL());
other[2].addActionListener(new BazL());
}
Button b = new Button("Swap Menus");
public MenuNew() {
FL fl = new FL();
for(int i = 0; i < flavors.length; i++) {
MenuItem mi = new MenuItem(flavors[i]);
mi.addActionListener(fl);
m.add(mi);
// Add separators at intervals:
if((i+1) % 3 == 0)
m.addSeparator();
}
for(int i = 0; i < safety.length; i++)
s.add(safety[i]);
f.add(s);
for(int i = 0; i < file.length; i++)
f.add(file[i]);
mb1.add(f);
mb1.add(m);
setMenuBar(mb1);
t.setEditable(false);
add(t, BorderLayout.CENTER);
// Set up the system for swapping menus:
b.addActionListener(new BL());
add(b, BorderLayout.NORTH);
for(int i = 0; i < other.length; i++)
fooBar.add(other[i]);
mb2.add(fooBar);
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
MenuBar m = getMenuBar();
if(m == mb1) setMenuBar(mb2);
else if (m == mb2) setMenuBar(mb1);
}
}
class ML implements ActionListener {
public void actionPerformed(ActionEvent e) {
MenuItem target = (MenuItem)e.getSource();
String actionCommand =
target.getActionCommand();
if(actionCommand.equals("Open")) {
String s = t.getText();
boolean chosen = false;
for(int i = 0; i < flavors.length; i++)
if(s.equals(flavors[i])) chosen = true;
if(!chosen)
t.setText("Choose a flavor first!");
else
t.setText("Opening "+ s +". Mmm, mm!");
} else if(actionCommand.equals("Exit")) {
dispatchEvent(
new WindowEvent(MenuNew.this,
WindowEvent.WINDOW_CLOSING));
}
}
}
class FL implements ActionListener {
public void actionPerformed(ActionEvent e) {
MenuItem target = (MenuItem)e.getSource();
t.setText(target.getLabel());
}
}
// Alternatively, you can create a different
// class for each different MenuItem. Then you
// Don't have to figure out which one it is:
class FooL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Foo selected");
}
}
class BarL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Bar selected");
}
}
class BazL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Baz selected");
}
}
class CMIL implements ItemListener {
public void itemStateChanged(ItemEvent e) {
CheckboxMenuItem target =
(CheckboxMenuItem)e.getSource();
String actionCommand =
target.getActionCommand();
if(actionCommand.equals("Guard"))
t.setText("Guard the Ice Cream! " +
"Guarding is " + target.getState());
else if(actionCommand.equals("Hide"))
t.setText("Hide the Ice Cream! " +
"Is it cold? " + target.getState());
}
}
public static void main(String[] args) {
MenuNew f = new MenuNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(300,200);
f.setVisible(true);
}
} ///:~
#p#分页标题#e#
在我们开始初始化节(由注解“Initialization code:”后的右大括号指明)的前面部门的代码同先前(Java 1.0版)版内情同。这里我们可以留意到项目吸收器和行动吸收器被附加在差异的菜单组件上。
Java 1.1支持“菜单快捷键”,因此我们可以选择一个菜单项目操作键盘替代鼠标。这十分的简朴;我们只要利用过载菜单项构建器配置第二个自变量为一个MenuShortcut(菜单快捷键事件)工具即可。菜单快捷键构建器配置重要的要领,当它按下时不行思议地显示在菜单项上。上面的例子增加了Control-E到“Exit”
菜单项中。
我们同样会留意setActionCommand()的利用。这看似一点生疏因为在各类环境下“action command”完全同菜单组件上的标签一样。为什么不正好利用标签取代可选择的字符串呢?这个困难是国际化的。假如我们从头用其它语言写这个措施,我们只需要改变菜单中的标签,并不审查代码中大概包括新错误的所有逻辑。因此使这对查抄文字字符串连系菜单组件的代码而言变得简朴容易,当菜单标签能改变时“行动指令”可以不作任何的改变。所有这些代码同“行动指令”一同事情,因此它不会受改变菜单标签的影响。留意在这个措施中,不是所有的菜单组件都被它们的行动指令所审查,因此这些组件都没有它们的行动指令集。
大大都的构建器同前面的一样,将几个挪用的异常增加到吸收器中。大量的事情产生在吸收器里。在前面例子的BL中,菜单瓜代产生。在ML中,“寻找ring”要领被作为行动事件(ActionEvent)的资源并对它举办造型送入菜单项,然后获得行动指令字符串,再通过它去贯串串联组,虽然条件是对它举办声明。这些大大都同前面的一样,但请留意假如“Exit”被选中,通过进入封装类工具的句柄(MenuNew.this)并建设一个WINDOW_CLOSING事件,一个新的窗口事件就被建设了。新的事件被分派到封装类工具的dispatchEvent()要领,然后竣事挪用windowsClosing()内部帧的窗口吸收器(这个吸收器作为一个内部类被建设在main()里),好像这是“正常”发活跃静的要领。通过这种机制,我们可以在任何环境下迅速处理惩罚任何的信息,因此,它很是的强大。
FL吸收器是很简朴尽量它能处理惩罚非凡菜单的所有差异的特色。假如我们的逻辑十分的简朴明白,这种要领对我们就很有用处,但凡是,我们利用这种要领时需要与FooL,BarL和BazL一道利用,它们每个都附加到一个单独的菜单组件上,因此一定无需测试逻辑,而且使我们正确地辨识出谁挪用了吸收器。这种要领发生了大量的类,内部代码趋向于变得小巧和处理惩罚起来简朴、安详。
7. 对话框
在这个例子里直接重写了早期的ToeTest.java措施。在这个新的版本里,任何事件都被安顿进一个内部类中。固然这完全消除了需要记录发生的任何类的贫苦,作为ToeTest.java的一个例子,它能使内部类的观念变得不那遥远。在这点,内嵌类被嵌套达四层之深!我们需要的这种设计抉择了内部类的利益是否值得增加越发巨大的事物。别的,当我们建设一个非静态的内部类时,我们将绑缚非静态类到它周围的类上。有时,单独的类可以更容易地被复用。
//: ToeTestNew.java
// Demonstration of dialog boxes
// and creating your own components
import java.awt.*;
import java.awt.event.*;
public class ToeTestNew extends Frame {
TextField rows = new TextField("3");
TextField cols = new TextField("3");
public ToeTestNew() {
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(p, BorderLayout.NORTH);
Button b = new Button("go");
b.addActionListener(new BL());
add(b, BorderLayout.SOUTH);
}
static final int BLANK = 0;
static final int XX = 1;
static final int OO = 2;
class ToeDialog extends Dialog {
// w = number of cells wide
// h = number of cells high
int turn = XX; // Start with x's turn
public ToeDialog(int w, int h) {
super(ToeTestNew.this,
"The game itself", false);
setLayout(new GridLayout(w, h));
for(int i = 0; i < w * h; i++)
add(new ToeButton());
setSize(w * 50, h * 50);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
dispose();
}
});
}
class ToeButton extends Canvas {
int state = BLANK;
ToeButton() {
addMouseListener(new ML());
}
public void paint(Graphics g) {
int x1 = 0;
int y1 = 0;
int x2 = getSize().width - 1;
int y2 = getSize().height - 1;
g.drawRect(x1, y1, x2, y2);
x1 = x2/4;
y1 = y2/4;
int wide = x2/2;
int high = y2/2;
if(state == XX) {
g.drawLine(x1, y1,
x1 + wide, y1 + high);
g.drawLine(x1, y1 + high,
x1 + wide, y1);
}
if(state == OO) {
g.drawOval(x1, y1,
x1 + wide/2, y1 + high/2);
}
}
class ML extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if(state == BLANK) {
state = turn;
turn = (turn == XX ? OO : XX);
}
else
state = (state == XX ? OO : XX);
repaint();
}
}
}
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
Dialog d = new ToeDialog(
Integer.parseInt(rows.getText()),
Integer.parseInt(cols.getText()));
d.show();
}
}
public static void main(String[] args) {
Frame f = new ToeTestNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(200,100);
f.setVisible(true);
}
} ///:~
#p#分页标题#e#
由于“静态”的对象只能位于类的外部一级,所以内部类不行能拥有静态数据可能静态内部类。
8. 文件对话框
这个例子是直接用新事件模子对FileDialogTest.java修改而来。
//: FileDialogNew.java
// Demonstration of File dialog boxes
import java.awt.*;
import java.awt.event.*;
public class FileDialogNew extends Frame {
TextField filename = new TextField();
TextField directory = new TextField();
Button open = new Button("Open");
Button save = new Button("Save");
public FileDialogNew() {
setTitle("File Dialog Test");
Panel p = new Panel();
p.setLayout(new FlowLayout());
open.addActionListener(new OpenL());
p.add(open);
save.addActionListener(new SaveL());
p.add(save);
add(p, BorderLayout.SOUTH);
directory.setEditable(false);
filename.setEditable(false);
p = new Panel();
p.setLayout(new GridLayout(2,1));
p.add(filename);
p.add(directory);
add(p, BorderLayout.NORTH);
}
class OpenL implements ActionListener {
public void actionPerformed(ActionEvent e) {
// Two arguments, defaults to open file:
FileDialog d = new FileDialog(
FileDialogNew.this,
"What file do you want to open?");
d.setFile("*.java");
d.setDirectory("."); // Current directory
d.show();
String yourFile = "*.*";
if((yourFile = d.getFile()) != null) {
filename.setText(yourFile);
directory.setText(d.getDirectory());
} else {
filename.setText("You pressed cancel");
directory.setText("");
}
}
}
class SaveL implements ActionListener {
public void actionPerformed(ActionEvent e) {
FileDialog d = new FileDialog(
FileDialogNew.this,
"What file do you want to save?",
FileDialog.SAVE);
d.setFile("*.java");
d.setDirectory(".");
d.show();
String saveFile;
if((saveFile = d.getFile()) != null) {
filename.setText(saveFile);
directory.setText(d.getDirectory());
} else {
filename.setText("You pressed cancel");
directory.setText("");
}
}
}
public static void main(String[] args) {
Frame f = new FileDialogNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(250,110);
f.setVisible(true);
}
} ///:~
假如所有的改变是这样的容易那将有多棒,但至少它们已足够容易,而且我们的代码已受益于这改造的可读性上。
