JAVA.SWT/JFace: JFace篇之首选项2010年08月11日 星期三 10:36《Eclipse SWT/JFACE 核心应用》 清华大学出版社 18 首选项
在一个应用系统中,首选项是可以根据用户的喜好来设定的,一般是以键(key)/值(value)来保存的。
18.1 首选项概述
有关保存首选项设置的类有:
◆ PreferenceStore:可以将设置以key/value的形式保存为文件,也可以载入文件后方便的获取所设定的值。
◆ PreferenceConverter:保存为文件的首选项为字符串的形式,对应像颜色、字体这些对象,无法直接保存为字符串,使用该类转换,将颜色保存为字符串的样式,并且将字符串转化为颜色对象。
有关首选项的设置的类有:
◆ FieldEditor:这是一个抽象类,虽然对首选项的设置可以使用最基本的标签、按钮等SWT控件实现,但是会很麻烦,为了简化创建各种设置的选项,可以使用FieldEditor对象创建常用的控件。
◆ BooleanFieldEditor:布尔型选项的设置。
◆ IntegerFieldEditor:整型值设置。
◆ StringFieldEditor:字符串型值的设置。
◆ RadioGroupFieldEditor:分组面板型的设置。
◆ ColorFieldEditor:颜色值的设置。
◆ FontFieldEditor:字体型值的设置。
◆ DirectoryFieldEditor:选择文件目录的设置。
◆ FileFieldEditor:选择文件的设置。
◆ PathEditor:选择路径的设置。
有关显示首选项页面的类有:
◆ PreferencePage:表示一个首选项页面,类似于向导式对话框中的一个向导页面WizardPage。
◆ PreferenceNode:浏览首选项的树型菜单的一个节点,一个节点对应一个首选项页面PreferencePage。
◆ PreferenceManager:负责管理每个节点和首选项页面,包括树的结构等。
◆ PreferenceDialog:显示首选项的对话框容器。
18.2 保存首选项的设置
保存首选项的类PreferenceStore。Java中使用.properties为扩展名的文件来保存首选项的设置。
1. 首选项值的设置和获取
首选项的设置是以key和value格式来表示的,如下:
Password=123
UserName=Janet
Database=mysql
要保存这样一个格式的文件代码如下:
PreferenceStore preferenceStore = new PreferenceStore("F:\\myPreference.properties");
preferenceStore.setValue("Database", "mysql");
preferenceStore.setValue("UserName", "Janet");
preferenceStore.setValue("Password", "123");
try {
preferenceStore.save();
} catch (IOException e) {
e.printStackTrace();
}
读取设置的值:
PreferenceStore preferenceStore = new PreferenceStore("F:\\myPreference.properties");
try {
preferenceStore.load(); // 装载文件
} catch (IOException e) {
e.printStackTrace();
}
String database = preferenceStore.getString("Database");
设置默认值:
setDefaultXXX。
当通过get方法获取一个设置时,程序首先查找保存的.properties文件中是否已设置了该值,如果没有则返回该选项的默认值。
2. 保存首选项所涉及的事件
当某个选项值改变时出发PropertyChangeEvent事件,如下:
preferenceStore.addPropertyChangeListener(new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals("Database")) {
System.out.println("old value:" + event.getOldValue());
System.out.println("new value:" + event.getNewValue());
}
}
});
preferenceStore.setValue("Database", "sqlserver"); // 触发事件
18.3 显示首选项页面
1. 创建一个首选项页面
package www.swt.com.ch18;
import org.eclipse.jface.preference.IPreferenceStore;
public class SystemSettingPage extends PreferencePage {
public SystemSettingPage() {
}
private Text userName;
private Text password;
//该方法为必须实现的方法,在此方法中创建页面上的各种控件
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
//获取保存此页面的PreferenceStore对象
IPreferenceStore preferenceStore = getPreferenceStore();
new Label(composite, SWT.LEFT).setText("登录用户名:");
userName = new Text(composite, SWT.BORDER);
userName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//设置用户名为保存在文件中的值
userName.setText(preferenceStore.getString(Constants.USER_NAME));
new Label(composite, SWT.LEFT).setText("登录密码:");
password = new Text(composite, SWT.BORDER);
password.setEchoChar('*');
password.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//设置密码为保存在文件中的值
password.setText(preferenceStore.getString(Constants.PASSWORD));
return composite;
}
/*
* (非 Javadoc)
*
* @see org.eclipse.jface.preference.PreferencePage#performDefaults()
* 覆盖父类中的方法,但单击“恢复默认值”按钮时调用该方法
*/
protected void performDefaults() {
IPreferenceStore preferenceStore = getPreferenceStore();
userName.setText( preferenceStore.getDefaultString(Constants.USER_NAME));
password.setText( preferenceStore.getDefaultString(Constants.PASSWORD));
}
/*
* (非 Javadoc)
*
* @see org.eclipse.jface.preference.PreferencePage#performOk()
* 覆盖父类中的方法,但单击“应用”按钮时调用该方法
*/
public boolean performOk() {
IPreferenceStore preferenceStore = getPreferenceStore();
if (userName != null)
preferenceStore.setValue(Constants.USER_NAME, userName.getText());
if (password != null)
preferenceStore.setValue(Constants.PASSWORD, password.getText());
return true;
}
/*
* (非 Javadoc)
*
* @see org.eclipse.jface.preference.PreferencePage#contributeButtons(org.eclipse.swt.widgets.Composite)
*/
protected void contributeButtons(Composite parent) {
// super.contributeButtons(parent);
Button bt1 = new Button(parent, SWT.NONE);
bt1.setText("按钮一");
((GridLayout) parent.getLayout()).numColumns++;
Button bt2 = new Button(parent, SWT.NONE);
bt2.setText("按钮二");
((GridLayout) parent.getLayout()).numColumns++;
}
}
从以上代码中可以总结出,创建一个首选项页面时需要注意以下问题:
◆ 每个首选项页面都要继承自PreferencePage类,而且必须实现createContents的抽象方法。
◆ 在createContents方法中可以创建页面的各种控件。
◆ 覆盖父类的performDefaults方法可以添加“恢复缺省值”按钮的操作,覆盖父类中的performOk方法,可以添加“应用”按钮的操作。
2. 创建首选项页面所对应的节点
节点所对应的类为PreferenceNode类。该类的构造方法有3个,如下:
◆ PreferenceNode(String id):id为标识该节点的字符,使用该构造函数需要使用setPage方法将一个节点对象与一个页面对象关联起来,如下:
SystemSettingPage system = new SystemSettingPage();
PreferenceNode node = new PreferenceNode("System");
node.setPage(system);
◆ PreferenceNode(String id, IPreferencePage preferencePage):id为该节点的唯一标识符,PreferencePage为该节点对应的页面。
SystemSettingPage system = new SystemSettingPage();
PreferenceNode node = new PreferenceNode("System", system);
◆ PreferenceNode(String id, String label, ImageDescriptor image, String className):id为该节点的唯一标识符,label为节点显示的名称,image为节点的图标,className为该节点所对应页面对象类的名称,注意是全称,包括所在的包名。还可以另一种方式获得类的全称:SystemSettingPage.class.getName(),也可以动态的获得该类的全称。
PreferenceNode nodeOne = new PreferenceNode("System", "系统设置",
ImageDescriptor.createFromFile(Constants.class, "tree_mode.gif"), // 节点的图标
SystemSettingPage.class.getName()); // 所对应的页面类的全称
一个PreferenceNode节点对象不仅保存了该节点所关联的首选项页面,还保存了该节点的其他信息,包括子节点等。
3. 显示首选项对话框
PreferenceManager负责管理所有的节点。该类有两个构造方法:
◆ PreferenceManager():无参的构造函数。使用默认的“.”字符作为分隔符使用该构造方法:
PreferenceManager manager = new PreferenceManager();
◆ PreferenceManager(char separatorChar):separatorChar为路径分隔符。将一个节点添加到PreferenceManager对象使用以下两种方法:
◇ addToRoot(IPreferenceNode node):添加到根节点中。
//创建一个PreferenceManager对象
PreferenceManager manager = new PreferenceManager();
//创建一个节点对象
PreferenceNode nodeOne = new PreferenceNode("System", "系统设置", null, SystemSettingPage.class.getName());
//将该节点添加到根节点中
manager.addToRoot(nodeOne);
◇ addTo(String path, IPreferenceNode node):将一个节点添加到指定路径的节点上,其中path为指定的路径,node为要添加的节点。
最后,使用PreferenceDialog创建将树型导航栏和选项页面显示出来:
package www.swt.com.ch18;
import java.io.IOException;
public class PreferenceTest {
public static void main(String[] args) {
Display display = new Display();
//创建一个PreferenceManager对象
PreferenceManager manager = new PreferenceManager();
//创建一个节点对象
PreferenceNode nodeOne = new PreferenceNode("System", "系统设置", null, SystemSettingPage.class.getName());
//将该节点添加到根节点中
manager.addToRoot(nodeOne);
//创建两个节点对象
PreferenceNode one = new PreferenceNode("one", "第一页", null, PageOne.class.getName());
PreferenceNode two = new PreferenceNode("two", "第二页", null, PageTwo.class.getName());
//将第一页节点附加到System路径下
manager.addTo("System",one);
//将第二页节点附加到System.one路径下
manager.addTo("System.one",two);
PreferenceNode editorOne = new PreferenceNode("one", "编辑字段", null, FieldEditorPage.class.getName());
manager.addToRoot(editorOne);
/*********************
//第二页节点为第一页节点的子节点
one.add( two );
//第一页节点为系统设置节点的子节点
nodeOne.add(one);
**********************/
//manager.addTo("System",one);
//manager.addTo("System.one",two);
//定义一个首选项对话框,并将manager作为参数传入
PreferenceDialog dlg = new PreferenceDialog(null, manager);
//注册页面切换事件
dlg.addPageChangedListener( new IPageChangedListener(){
//当页面切换时
public void pageChanged(PageChangedEvent event) {
//获得当前页面
IPreferencePage page = (IPreferencePage)event.getSelectedPage();
//输出当前页面的标题
System.out.println(page.getTitle());
}
});
//创建保存选项设置值对象
PreferenceStore preferenceStore = new PreferenceStore("F:\\myPreference.properties");
try {
//装载该文件中的设置值
preferenceStore.load();
//将该设置赋值给该对话框
dlg.setPreferenceStore(preferenceStore);
//打开对话框
dlg.open();
//最后关闭对话框后,保存当前设置
preferenceStore.save();
} catch (IOException e) {
e.printStackTrace();
}
display.dispose();
}
}
18.4 创建树型的导航菜单
要创建树型菜单,有两种方法,一种是在创建节点时就创建了该节点的子节点,这种情况下使用PreferenceNode对象的add方法为节点添加子节点。另一种方法是通过PreferenceManager对象的addTo方法为指定路径下添加节点。
两个选项页的代码如下:
package www.swt.com.ch18;
import org.eclipse.jface.preference.PreferencePage;
public class PageOne extends PreferencePage {
protected Control createContents(Composite parent) {
return parent;
}
/*
* (非 Javadoc)
*
* @see org.eclipse.jface.preference.PreferencePage#contributeButtons(org.eclipse.swt.widgets.Composite)
*/
protected void contributeButtons(Composite parent) {
// super.contributeButtons(parent);
Button bt1 = new Button(parent, SWT.NONE);
bt1.setText("按钮一");
((GridLayout) parent.getLayout()).numColumns++;
Button bt2 = new Button(parent, SWT.NONE);
bt2.setText("按钮二");
((GridLayout) parent.getLayout()).numColumns++;
}
}
另外一个选项页:
package www.swt.com.ch18;
import org.eclipse.jface.preference.PreferencePage;
public class PageTwo extends PreferencePage{
protected Control createContents(Composite parent) {
return parent;
}
}
第一种方法创建树型菜单:
// 创建一个PreferenceManager对象
PreferenceManager manager = new PreferenceManager();
// 创建一个节点对象
PreferenceNode nodeOne = new PreferenceNode("System", "系统设置", null, SystemSettingPage.class.getName());
// 将该节点添加到根节点
manager.addToRoot(nodeOne);
// 创建两个节点对象
PreferenceNode one = new PreferenceNode("one", "第一页", null, PageOne.class.getName());
PreferenceNode two = new PreferenceNode("two", "第二页", null, PageTwo.class.getName());
// 第二页节点为第一页节点的子节点
one.add(two);
// 第一页节点为系统设置节点的子节点
nodeOne.add(one);
第二种方法创建树型菜单:
// 创建一个PreferenceManager对象
PreferenceManager manager = new PreferenceManager();
// 创建一个节点对象
PreferenceNode nodeOne = new PreferenceNode("System", "系统设置", null, SystemSettingPage.class.getName());
// 将该节点添加到根节点
manager.addToRoot(nodeOne);
// 创建两个节点对象
PreferenceNode one = new PreferenceNode("one", "第一页", null, PageOne.class.getName());
PreferenceNode two = new PreferenceNode("two", "第二页", null, PageTwo.class.getName());
// 将第一页节点附加到System路径下
manager.addTo("System", one);
// 将第二页节点附加到System.one路径下
manager.addTo("System.one", two);
18.5 首选项的选项设置
对于首选项的设置,可以使用SWT基本的控件就可以实现,但为了方便创建设置的选项,JFace提供了常用的一些设置选项值的字段对象。
1. 字段编辑器概述
字段编辑器类FieldEditor类是一个抽象类,创建字段编辑器要实现其方法的子类。使用字段编辑器的好处是,不必考虑对选项的保存,只需要创建使用的编辑器对象即可。
2. 使用字段编辑器基本步骤
package www.swt.com.ch18;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.ColorFieldEditor;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.FileFieldEditor;
import org.eclipse.jface.preference.FontFieldEditor;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.PathEditor;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.jface.preference.ScaleFieldEditor;
import org.eclipse.jface.preference.StringFieldEditor;
public class FieldEditorPage extends FieldEditorPreferencePage {
public FieldEditorPage() {
super(GRID);//页面的样式,还可以使用FLAT常量
}
//该方法为实现父类中的抽象方法,在该方法中添加所需的编辑器对象
protected void createFieldEditors() {
//创建一个字符型编辑器对象
StringFieldEditor userName = new StringFieldEditor(
Constants.USER_NAME, //选项的key值
"登录用户名:", //显示的标签名
getFieldEditorParent());//该字段编辑器的父类面板
//调用父类方法,将该方法添加到该页中
addField(userName);
// /*
BooleanFieldEditor bfe = new BooleanFieldEditor("show","Boolean",getFieldEditorParent());
addField(bfe);
ColorFieldEditor cfe = new ColorFieldEditor("color","Color",getFieldEditorParent());
addField(cfe);
FontFieldEditor ffe = new FontFieldEditor("font","Font",getFieldEditorParent());
addField(ffe);
PathEditor pfe = new PathEditor("path","Path","请选择所选的路径",getFieldEditorParent());
addField(pfe);
RadioGroupFieldEditor rgfe = new RadioGroupFieldEditor(
"group", //选项的key
"RadioGroup",//分组框显示的文本
2,//一行显示的单选按钮个数
new String[][] { { "Radio one", "one"}, {"Radio two", "two"},{"Radio three", "three"} },//单选按钮的标签和值
getFieldEditorParent(),//父类的面板
true);//true表示使用分组面板,false将使用普通的面板
addField(rgfe);
ScaleFieldEditor sfe = new ScaleFieldEditor("scale","Scale",getFieldEditorParent(),0,100,5,10);
addField(sfe);
IntegerFieldEditor ife = new IntegerFieldEditor("int","Int",getFieldEditorParent());
ife.setLabelText("这是int");
addField(ife);
DirectoryFieldEditor dfe = new DirectoryFieldEditor("dirctory","Directory",getFieldEditorParent());
addField(dfe);
FileFieldEditor filefe = new FileFieldEditor("file","File",getFieldEditorParent());
addField(filefe);
// */
}
}
显示效果:
使用字段编辑器应注意以下方面:
◆ 要使用字段编辑器,创建首选项页面时要继承自FieldEditorPreferencePage类,而不是继承自PreferencePage类,而且要实现createFieldEditors抽象方法。在该方法中创建各种编辑器对象。
◆ 创建编辑器对象时,至少要有3个参数,选项的key值、显示的标签名和该字段编辑器的父类面板。其中选项的key值,即为保存为文件中的key值,编辑对象会自动显示文件中所设置的值。
◆ 创建完编辑器对象后,调用父类的addField方法,将该编辑器对象添加到页面中。
◆ 使用编辑器时,不需要编写单击“恢复缺省值”和“应用”按钮的操作,这是因为FieldEditorPreferencePage是PreferencePage的子类,在该类中覆盖了PreferencePage类中的performOk方法,并且循环所有的字段编辑器对象,保存到存储设置的对象中。如下图所示,对界面上的内容修改后,点击“确定”关闭,重新打开程序时,显示的是上次设定的内容。如果点击“取消”关闭窗口,则重新打开程序时,上次修改的内容不会生效。
当输入的值不合法时,提示如下:
18.6 自定义首选项页面
每个首选项页面都有一个“恢复缺省值”按钮和“应用”按钮。若想自定义首选项页面上的按钮,需要覆盖父类的contributeButtons方法。
参考本文中的SystemSettingPage。
在创建完一个按钮后,要调用((GridLayout) parent.getLayout()).numColumns++;方法,将父类面板中的列数加1。
18.7 首选项的事件处理
当切换首选项页面时会触发PageChangedEvent事件。
PreferenceDialog dlg = new PreferenceDialog(null, manager);
//注册页面切换事件
dlg.addPageChangedListener( new IPageChangedListener(){
//当页面切换时
public void pageChanged(PageChangedEvent event) {
//获得当前页面
IPreferencePage page = (IPreferencePage)event.getSelectedPage();
//输出当前页面的标题
System.out.println(page.getTitle());
}
});