向导式对话框是一种非常友好的界面,它能够引导用户一步步的输入信息.Eclipse的"新建项目",就是这样的向导式对话框.
在Eclipse中向导式对话框的开发是很简单的,它由WizardDialog类来创建向导式对话框.
WizardDialog的继承关系图:
当然仅仅有WizardDialog还是不够的,还需要有Wizard类,WizardPage类来辅助使用.
向导式对话框中每一步显示的页面由WizardPage类负责创建,Wizard类则负责管理WizardPage页面.
WizardDialog最简单,它和InputDialog等的使用相同,所以在向导式对话框的创建中,Wizard和Wizardpage的编程才是重点.
WizardDialog,Wizard,WizardPage三者的关系图如下:
通过一个例子了解:如何创建向导式的对话框,如何给向导式的对话框设置初始值.
如何对值做验证,如何取得向导式对话框中的值,实际开发中也无非就是这些内容,只不过界面组件更多了一些罢了.
向导式对话框使用的时的注意事项
向导式对话框在单击"下一步","上一步"按钮时都会执行MyWizard类的canFinish方法,因此在写
这种方法的时候要注意保证程序的执行效率.
向导式对话框实例:
实现一个简单的向导式对话框,此对话框用于手机用户的资料.它有两个页面,第一个页面收集姓名和Email,第二页面收集学校.最后单击"完成"按钮结束向导后,输出各页面收集到的信息.
如何创建向导式对话框:如何给向导式对话框设初始值:如何对值做验证;如何取得向导式对话框中的值.实际开发中也无非是这些内容.只不过界面组件更多一些罢了.
实例的代码如下:
(1)主程序中对WizardDialog的使用.将Wizard作为参数传给WizardDialog.代码如下:
WizardDialog1.java
1 import org.eclipse.jface.wizard.WizardDialog; 2 import org.eclipse.swt.widgets.Display; 3 import org.eclipse.swt.widgets.Shell; 4 5 public class WizardDialog1 { 6 public static void main(String[] args) { 7 Display display = Display.getDefault(); 8 Shell shell = new Shell(display); 9 10 WizardDialog dialog = new WizardDialog(shell, new MyWizard()); 11 dialog.setPageSize(-1, 60); // dialog大小,-1是指让宽度自动调整 12 dialog.open(); 13 14 display.dispose(); 15 } 16 }
(2)WizardDialog用到的MyWizard类的代码如下:
MyWizard类主要是改写父类Wizard的3个方法:addPages.canFinish和performFinish.
在addPages方法中加入页面和为页面设置初始值:在canFinish方法中判断"完成"按钮是否可用,在performFinish方法中编写退出向导时候处理程序.
MyWizard.java
1 import org.eclipse.jface.wizard.Wizard; 2 3 public class MyWizard extends Wizard { 4 // 把两页面对象定义成实例变量,使其他方法能访问得到 5 private NamePage namePage;// 页面一,继承自WizardPage类 6 private SchoolPage schoolPage;// 页面二,继承自WizardPage类 7 8 // 在此方法将两页面加入并设置初值 9 public void addPages() { 10 // 创建页面对象,并设置页面的名称 11 namePage = new NamePage("namePage"); 12 schoolPage = new SchoolPage("schoolPage"); 13 // 设置页面的初始值 14 namePage.setName("陈刚"); 15 namePage.setEmail("glchengang@yeah.net"); 16 schoolPage.setSchool("广西师范大学"); 17 // 加入两页面,加入的顺序就是界面上显示的顺序 18 addPage(namePage); 19 addPage(schoolPage); 20 } 21 22 // 由此方法判断“完成”按钮何时有效。返回true则有效,false无效 23 public boolean canFinish() { 24 System.out.println("aa"); 25 // 设置成:当还没到最后一页时“完成”按钮无效 26 if (this.getContainer().getCurrentPage() != schoolPage) 27 return false; 28 return super.canFinish(); 29 } 30 31 // 当单击“完成”按钮退出向导时,将执行此方法 32 public boolean performFinish() { 33 // 取出各页面的值,并打印输出 34 System.out.println(namePage.getName()); 35 System.out.println(namePage.getEmail()); 36 System.out.println(schoolPage.getSchool()); 37 return true; 38 } 39 }
程序说明:
向导式对话框在单击"下一步","上一步"按钮时都会执行canFinish方法来重置底部按钮的有效状态,因此canFinish方法中的代码的执行效率不要太低.
(3)创建两个继承自WizardPage类:NamePage和SchoolPage.在这两个类中创建页面上的界面组件,添加组件的设值和取值方法.NamePage页的代码如下,里面 有多次用到了Apache的Common软件包:
NamePage.java
1 import org.apache.commons.lang.StringUtils; 2 import org.apache.commons.validator.EmailValidator; 3 import org.eclipse.jface.wizard.WizardPage; 4 import org.eclipse.swt.SWT; 5 import org.eclipse.swt.events.ModifyEvent; 6 import org.eclipse.swt.events.ModifyListener; 7 import org.eclipse.swt.layout.GridData; 8 import org.eclipse.swt.layout.GridLayout; 9 import org.eclipse.swt.widgets.Composite; 10 import org.eclipse.swt.widgets.Text; 11 12 public class NamePage extends WizardPage { 13 private String name; 14 private String email; 15 private Text nameText; 16 private Text emailText; 17 18 // 必须继承父类的构造函数 19 protected NamePage(String pageName) { 20 super(pageName); 21 } 22 23 // 改写自父类的方法,在此方法中构建页面上的界面组件。注意不要在传入参数parent基础直接创建界面元素,而应在一个新面板topComp上创建 24 public void createControl(Composite parent) { 25 // 每页的提示信息 26 setTitle("用户信息"); 27 setMessage("请输入您的姓名及Email", INFORMATION); 28 // 创建一个页面组件的底层面板,并使用GridLayout布局 29 Composite topComp = new Composite(parent, SWT.NULL); 30 topComp.setLayout(new GridLayout()); 31 // 创建“姓名”文本框 32 nameText = new Text(topComp, SWT.BORDER); 33 nameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 34 // 将null转化成"",等效于 name== null ? "" : name 35 nameText.setText(StringUtils.defaultString(name)); 36 // 创建“Email”文本框 37 emailText = new Text(topComp, SWT.BORDER); 38 emailText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 39 emailText.setText(StringUtils.defaultString(email)); 40 // 给两文本框加入监听器 41 MyModifyListener listener = new MyModifyListener(); 42 nameText.addModifyListener(listener); 43 emailText.addModifyListener(listener); 44 // 必须要的一行 45 setControl(topComp); 46 } 47 48 // 此监听器,每次文本框里的文本变动都会触发,触发频度较大 49 private class MyModifyListener implements ModifyListener { 50 public void modifyText(ModifyEvent e) { 51 setPageComplete(false); // 先使“完成”和“下一步”两按钮无效 52 // 用Apache Commons Lang的StringUtils可以检查出全角空格 53 name = nameText.getText().trim();// 设回实例变量name 54 if (StringUtils.isBlank(name)) { 55 setErrorMessage("姓名不能为空"); // 提示错误信息 56 return; 57 } 58 // 用了Apache Commons Validator的 EmailValidator来检查Email写法的合法性 59 EmailValidator validator = EmailValidator.getInstance(); 60 email = emailText.getText().trim();// 设回实例变量email 61 if (!validator.isValid(email)) { 62 setErrorMessage("Email的格式错误"); 63 return; 64 } 65 // 前面的检查都通过后...... 66 setErrorMessage(null); // 消除对话框上的出错提示 67 setPageComplete(true); // 使“完成”和“下一步”两按钮可用 68 } 69 } 70 71 // --------相应的Setter/Getter方法 --------------- 72 public String getName() { 73 return name; 74 } 75 76 public void setName(String string) { 77 name = string; 78 } 79 80 public String getEmail() { 81 return email; 82 } 83 84 public void setEmail(String string) { 85 email = string; 86 } 87 }
程序说明:"不要重新发明轮子"是软件界的一句著名的俗语,Apache提供了很多所需的软件包,而且都经过了严格的测试和实践检验的,我们有什么理由自己再去写一遍重复的代码呢?示例中的EmailValidator,StringUtils都是Apache的Common工具集中的类,前者是Validator包的,后者是Lang包的.其中,Validator包还需要正规表达式的软件包,ORO的支持.
第二个页面SchoolPage.java的代码和前面的NamePage类似:
SchoolPage.java
1 import org.apache.commons.lang.StringUtils; 2 import org.eclipse.jface.wizard.WizardPage; 3 import org.eclipse.swt.SWT; 4 import org.eclipse.swt.events.ModifyEvent; 5 import org.eclipse.swt.events.ModifyListener; 6 import org.eclipse.swt.layout.GridData; 7 import org.eclipse.swt.layout.GridLayout; 8 import org.eclipse.swt.widgets.Composite; 9 import org.eclipse.swt.widgets.Text; 10 11 public class SchoolPage extends WizardPage { 12 private String school; 13 private Text schoolText; 14 15 protected SchoolPage(String pageName) { 16 super(pageName); 17 } 18 19 public void createControl(Composite parent) { 20 // 每页的提示信息 21 setTitle("用户信息"); 22 setMessage("请输入您的学校的名称", INFORMATION); 23 // 创建一个组件的底层面板,并使用GridLayout布局 24 Composite topComp = new Composite(parent, SWT.NULL); 25 topComp.setLayout(new GridLayout()); 26 // 创建“学校”文本框 27 schoolText = new Text(topComp, SWT.BORDER); 28 schoolText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 29 schoolText.setText(StringUtils.defaultString(school)); 30 schoolText.addModifyListener(new MyModifyListener()); 31 this.setControl(topComp);// 必须要的一行 32 } 33 34 // 注释说明请参数NamePage页的监听器,两者现实相似。 35 private class MyModifyListener implements ModifyListener { 36 public void modifyText(ModifyEvent e) { 37 setPageComplete(false); 38 school = schoolText.getText().trim(); 39 if (StringUtils.isBlank(school)) { 40 setErrorMessage("学校名不能为空"); 41 return; 42 } 43 setErrorMessage(null); 44 setPageComplete(true); 45 } 46 } 47 48 // --------相应的Setter/Getter方法 --------------- 49 public String getSchool() { 50 return school; 51 } 52 53 public void setSchool(String string) { 54 school = string; 55 } 56 }
运行结果如下: