对话框是一个从其它窗口弹出的窗口。它的目标是处理惩罚一些非凡的争议和它们的细节而不使本来的窗口陷入杂乱之中。对话框大量在配置窗口的编程情况中利用,但就像前面提到的一样,鲜于在措施片中利用。
我们需要从对话类处担任以建设其它范例的窗口、像帧一样的对话框。和窗框差异,对话框不能拥有菜单条也不能改变光标,但除此之外它们十分的相似。一个对话框拥有机关打点器(默认的是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 components 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); } } 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); 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 static 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的构建器十分的简朴:它像我们所需要的一样增加一些按钮到GridLayout机关打点器中,然后调解每个按钮每边巨细为50个像素(假如我们不调解窗口,那么它就不会显示出来)。留意handleEvent()正好为WINDOW_DESTROY挪用dispose(),因此整个应用措施不会被封锁。
ToeTest配置整个应用措施以建设TextField(为输入按钮网格的行和列)和“go”按钮。我们会了解action()在这个措施中利用不太令人满足的“字符串匹配”技能来测试按钮的按下(请确定我们拼写和大写都是正确的!)。当按钮按下时,TextField中的数据将被取出,而且,因为它们在字符串布局中,所以需要操作静态的Integer.paresInt()要领来转酿成间断。一旦对话类被成立,我们就必需挪用show()要领来显示和激活它。
我们会留意到ToeDialog工具赋值给一个对话句柄 d。这是一个上溯造型的例子,尽量它没有真正地发生重要的差别,因为所有的事件都是show()挪用的。可是,假如我们想挪用ToeDialog中已经存在的一些要领,我们需要对ToeDialog句柄赋值,就不会在一个上溯中丢失信息。
1. 文件对话类
在一些操纵系统中拥有很多的非凡内建对话框去处理惩罚选择的事件,譬喻:字库,颜色,打印机以及雷同的事件。险些所有的操纵系统都支持打开和生存文件,可是,Java的FileDialog包更容易利用。虽然这会不再检测所有利用的措施片,因为措施片在当地磁盘上既不能读也不能写文件。(这会在新的欣赏器中互换措施片的信任干系。)
下面的应用措施运用了两个文件对话类的窗体,一个是打开,一个是生存。大大都的代码到如今已为我们所熟悉,而所有这些有趣的勾当产生在两个差异按钮单击事件的action()要领中。
//: FileDialogTest.java // Demonstration of File dialog boxes import java.awt.*; public class FileDialogTest extends Frame { TextField filename = new TextField(); TextField directory = new TextField(); Button open = new Button("Open"); Button save = new Button("Save"); public FileDialogTest() { setTitle("File Dialog Test"); Panel p = new Panel(); p.setLayout(new FlowLayout()); p.add(open); p.add(save); add("South", p); directory.setEditable(false); filename.setEditable(false); p = new Panel(); p.setLayout(new GridLayout(2,1)); p.add(filename); p.add(directory); add("North", p); } 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(evt.target.equals(open)) { // Two arguments, defaults to open file: FileDialog d = new FileDialog(this, "What file do you want to open?"); d.setFile("*.java"); // Filename filter d.setDirectory("."); // Current directory d.show(); String openFile; if((openFile = d.getFile()) != null) { filename.setText(openFile); directory.setText(d.getDirectory()); } else { filename.setText("You pressed cancel"); directory.setText(""); } } else if(evt.target.equals(save)) { FileDialog d = new FileDialog(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(""); } } else return super.action(evt, arg); return true; } public static void main(String[] args) { Frame f = new FileDialogTest(); f.resize(250,110); f.show(); } } ///:~
#p#分页标题#e#
对一个“打开文件”对话框,我们利用构建器配置两个自变量;首先是父窗口句柄,其次是FileDialog标题条的标题。setFile()要领提供一个初始文件名--也许当地操纵系统支持通配符,因此在这个例子中所有的.java文件最开头会被显示出来。setDirectory()要领选择文件抉择开始的目次(一般而言,操纵系统答允用户改变目次)。
show()呼吁直到对话类封锁才返回。FileDialog工具一直存在,因此我们可以从它哪里读取数据。假如我们挪用getFile()而且它返回空,这意味着用户退出了对话类。文件名和挪用getDirectory()要领的功效都显示在TextFields里。
按钮的生存事情利用同样的要领,除了因为FileDialog而利用差异的构建器。这个构建器配置了三个自变量而且第三的一个自变量必需为FileDialog.SAVE或FileDialog.OPEN。