1. JFace和SWT的关系:
a) 说明:JFace是完全基于SWT而实现的。他主要是通过封装了底层的一堆SWT控件,从而定制了一些程序员将会经常使用,而又比较复杂的控件,例如Viewer,Wizard等。
b) 结构图:
2. 一个JFace的例子:
a) 说明:JFace与SWT不同的地方包括程序员不用手动的启动消息循环;不需要创建Shell实例。
b) 代码:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test1 {
public static void main(String[] args) {
ApplicationWindow win = new ApplicationWindow(null);
win.setBlockOnOpen(true);
win.open();
Display.getCurrent().dispose();
}
}
c) 运行图:
3. JFace窗口的定制
a) 说明:由于JFace只是对SWT进行了封装,因此,为了对JFace的ApplicationWindow进行定制,我们需要获取在JFace中的Shell引用,。但这里存在一个问题,当我们需要定制控件树时,我们必须要在应用窗口显示以前,也就是ApplicationWindow的open()操作被调用以前,而另一方面,ApplicationWindow只有在open()操作被调用以后才会创建他的Shell实例,因此,这就导致了我们不能通过获取Shell实例的方法来实现JFace窗口的定制。
4. 通过扩展的方式定制JFace窗口
a) 说明:通过对ApplicationWindow进行子类化,我们可以实现JFace窗口的定制。在定制过程中,我们要做的就是实现那些用于创建控件的回调函数。
b) 结构图:
c) 代码:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test2 extends ApplicationWindow {
public Test2() {
super(null);
}
public Control createContents(Composite parent) {
parent.getShell().setText("Test2");
Button b = new Button(parent, SWT.PUSH);
b.setText("Hello World");
return b;
}
…
}
d) 运行图:
5. TreeViewer
a) 说明:Viewer是JFace当中最主要的控件之一。他以树形图的方式,对程序员所指定的内容进行浏览。Viewer是一个基于MVC模式的控件,其中TreeViewer是Viewer部分,他负责对内容进行显示,我们通过setInput()方法可以对需要显示的内容执行指定,但是TreeViewer本身并不对需要显示的内容进行处理,它把这个任务委派了给ContentProvider负责,由他来对需要显示的内容进行遍历和跟踪。如果没有LabelProvider,那么TreeViewer将会调用代显示内容的toString()方法,并把返回的值作为显示内容的名称,但由于这样可读性并不高,因此,我们另外提供一个LabelProvider,这个类的作用就是为代显示的内容提供一个可供阅读的标签。
b) 结构图:
c) 代码:
主程序:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test4 extends ApplicationWindow {
…
public Control createContents(Composite parent) {
TreeViewer tv = new TreeViewer(parent);
tv.setContentProvider(new Test3ContentProvider());
tv.setLabelProvider(new Test4LabelProvider());
tv.setInput(new File("D:/"));
return null;
}
…
}
ContentProvider:
public class Test3ContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object element) {
File parent = (File) element;
Object[] children = parent.listFiles();
if (children == null)
return new Object[0];
else
return children;
}
public Object getParent(Object child) {
return ((File) child).getParent();
}
public boolean hasChildren(Object element) {
Object[] children = getChildren(element);
return children.length == 0 ? false : true;
}
public Object[] getElements(Object element) {
return getChildren(element);
}
public void dispose() {}
public void inputChanged(Viewer v, Object o1, Object o2) {}
}
LabelProvider:
public class Test4LabelProvider extends LabelProvider {
public String getText(Object element) {
return ((File) element).getName();
}
}
d) 运行图:
6. TableViewer
a) 说明:TableViewer与TreeViewer类似,他们的区别只是显示的方式不一样。另外,针对TableViewer本身,我们需要增加一些额外的定制操作,我们需要显式的为TableViewer增加显示的列,对于ContentProvider,由于表格的方式不需要对项进行跟踪,所以相比之下,他要比TreeViewer中的ContentProvider要简单一些。而对于LabelProvider,由于现在涉及到多列内容的问题,因此我们需要把列的索引值考虑进去。这里有一点要特别留意的就是,由于TableViewer不对显式的内容进行跟踪,因此为了更新他内部的显示,我们使用了一种外部的,事件处理的方式,不断的修改TableViewer当中代显示的内容。
b) 结构图:
c) 代码:
主程序:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test5 extends ApplicationWindow {
private TreeViewer tv = null;
private TableViewer tablev = null;
…
public Control createContents(Composite parent) {
…
tablev = new TableViewer(form);
TableColumn tc = new TableColumn(tablev.getTable(), SWT.NONE);
tc.setText("Name");
tc.setWidth(100);
tablev.getTable().setHeaderVisible(true);
tablev.setContentProvider(new Test5ContentProvider());
tablev.setLabelProvider(new Test5TableLabelProvider());
tv.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent e) {
IStructuredSelection s = (IStructuredSelection) e.getSelection();
tablev.setInput(s.getFirstElement());
}
});
return null;
}
…
}
ContentProvider:
public class Test5ContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object element) {
File parent = (File) element;
Object[] children = parent.listFiles();
if (children == null)
return new Object[0];
else
return children;
}
public void dispose() {}
public void inputChanged(Viewer v, Object o1, Object o2) {}
}
LabelProvider:
public class Test5TableLabelProvider implements ITableLabelProvider {
public void addListener(ILabelProviderListener l) {}
public void dispose() {}
public boolean isLabelProperty(Object o, String s) {
return false;
}
public void removeListener(ILabelProviderListener l) {}
public Image getColumnImage(Object o, int i) {
return null;
}
public String getColumnText(Object o, int i) {
return ((File) o).getName();
}
}
d) 运行图:
7. 排序和过滤
a) 说明:在使用Viewer的同时,我们可以对需要显示的内容进行排序和过滤操作。其中ViewerSorter负责排序,他有两个方法category()和compare(),其中category()负责进行分类,分类后的权值越大,在显示时则排列的越后;分类完以后则调用compare()方法,进行类别内的排序。ViewerFilter负责进行过滤,他有一个select()方法。
b) 代码:
主程序:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test7 extends ApplicationWindow {
private TreeViewer tv = null;
private TableViewer tablev = null;
…
public Control createContents(Composite parent) {
…
tv.addFilter(new Test7Filter());
…
tablev.setSorter(new Test7Sorter());
…
}
…
}
ViewerSorter:
public class Test7Sorter extends ViewerSorter {
public int category(Object o) {
File f = (File) o;
return f.isDirectory() ? 0 : 1;
}
public int compare(Viewer v, Object o1, Object o2) {
return super.compare(v, o1, o2);
}
}
ViewerFilter:
public class Test7Filter extends ViewerFilter {
public boolean select(Viewer v, Object parent, Object e) {
return ((File) e).isDirectory();
}
}
c) 运行图:
8. 图片显示:
a) 说明:在SWT当中,图片是一个重量级的控件,因此,当使用完以后,我们需要进行显式的释放。而为了更好的对图像资源进行管理,JFace当中提供了用于对图片进行管理和引用的ImageRegistry和ImageDescriptor。其中ImageRegistry负责维护ImageDescriptor实例的索引,ImageDescriptor则是负责底层图像资源的管理。
b) 结构图:
c) 代码:
图片管理:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test6Util {
…
public static ImageRegistry getImageRegistry() {
if (reg == null) {
reg = new ImageRegistry();
reg.put("folder", ImageDescriptor
.createFromURL(newUrl("file:folder.gif")));
reg.put("file", ImageDescriptor
.createFromURL(newUrl("file:file.gif")));
}
return reg;
}
}
图片使用:
public class Test6TableLabelProvider implements ITableLabelProvider {
…
public Image getColumnImage(Object o, int i) {
if (i == 0) {
File f = (File) o;
if (f.isDirectory())
return Test6Util.getImageRegistry().get("folder");
else
return Test6Util.getImageRegistry().get("file");
} else
return null;
}
…
}
d) 运行图:
9. 增加菜单,状态栏,工具栏和操作等
a) 说明:在JFace当中增加菜单和状态栏等控件时,主要需要两个步骤,一是在构造函数当中调用对应的通知函数,二是实现用于增加这些控件的函数。
b) 代码:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test8 extends ApplicationWindow {
private TreeViewer tv = null;
private TableViewer tablev = null;
private Test8OpenAction aOpen = null;
private Test8EditAction aEdit = null;
private Test8AboutAction aAbout = null;
public Test8(Shell s) {
super(s);
aOpen = new Test8OpenAction(this);
aEdit = new Test8EditAction(this);
aAbout = new Test8AboutAction(this);
addStatusLine(); // 增加状态栏
addMenuBar(); // 增加菜单栏
addToolBar(SWT.WRAP | SWT.FLAT); // 增加工具栏
}
public Control createContents(Composite parent) {
…
/**
* 为TableViewer创建上下文菜单
*/
MenuManager mm = new MenuManager();
tablev.getTable().setMenu(mm.createContextMenu(tablev.getTable()));
mm.add(aOpen);
mm.add(aEdit);
mm.add(aAbout);
return null;
}
public MenuManager createMenuManager() {
MenuManager mm = new MenuManager();
MenuManager mmFile = new MenuManager("&File");
MenuManager mmEdit = new MenuManager("&Edit");
MenuManager mmAbout = new MenuManager("&About");
mmFile.add(aOpen);
mmEdit.add(aEdit);
mmAbout.add(aAbout);
mm.add(mmFile);
mm.add(mmEdit);
mm.add(mmAbout);
return mm;
}
public ToolBarManager createToolBarManager(int style) {
ToolBarManager tbm = new ToolBarManager(style);
tbm.add(aOpen);
tbm.add(aEdit);
tbm.add(aAbout);
return tbm;
}
…
}
public class Test8OpenAction extends Action {
private Test8 t = null;
public Test8OpenAction(Test8 t) {
this.t = t;
setText("&Open@Ctrl+O");
}
public void run() {
System.out.println("Hehe Open Action");
}
}
c) 运行图:
10. 向导
a) 说明:JFace提供了用于生成向导的类。Wizard和WizardPage。当我们需要显示一个向导时,我们需要为他创建一个向导对话框。对于Wizard我们需要实现两个方法,addPages(),用于添加向导页,performFinish(),当向导中的“Finish”按钮被按下时被调用。对于WizardPage,我们可以通过createControl()方法,构建向导页内的UI控件。另外WizardPage提供的setErrorMessage()方法可用于显示输入当中的出错信息,而setPageComplete()方法,则是用于表示当前页的输入是否已经结束,是否需要跳转到后一页。
b) 代码:
/**
* @author cenyongh@mails.gscas.ac.cn
*/
public class Test9 extends ApplicationWindow {
private Shell s = null;
…
public Control createContents(Composite parent) {
Button b = new Button(parent, SWT.PUSH);
b.setText("Open");
b.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Wizard w = new Test9Wizard();
WizardDialog dia = new WizardDialog(null, w);
dia.open();
}
});
return null;
}
…
}
向导:
public class Test9Wizard extends Wizard {
Test9Page1 p1 = null;
Test9Page2 p2 = null;
public Test9Wizard() {
super();
setNeedsProgressMonitor(true);
}
public void addPages() {
p1 = new Test9Page1("Info");
p2 = new Test9Page2("Other");
addPage(p1);
addPage(p2);
}
public boolean performFinish() {
String name = p1.getName();
String age = p1.getAge();
String phone = p2.getPhone();
String address = p2.getAddress();
return true;
}
}
向导页:
public class Test9Page1 extends WizardPage {
private String name = null;
private String age = null;
private Text t1 = null;
private Text t2 = null;
public Test9Page1(String name) {
super(name);
setTitle(name);
setMessage("Input your info detail");
try {
setImageDescriptor(ImageDescriptor.createFromURL(new URL("file:file.gif")));
} catch (Exception e) {
e.printStackTrace();
}
}
public void createControl(Composite parent) {
Group g = new Group(parent, SWT.BORDER);
…
t1.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
validate();
}
});
…
setControl(g);
setPageComplete(false);
}
private void validate() {
name = t1.getText().trim();
age = t2.getText().trim();
if (name.equals("")) {
setErrorMessage("Name is null");
setPageComplete(false);
} else if (age.equals("")) {
setErrorMessage("Age is null");
setPageComplete(false);
} else {
setErrorMessage(null);
setPageComplete(true);
}
}
public String getAge() {
return age;
}
public String getName() {
return name;
}
}
c) 运行图:
11. 参考资料:
http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-ecgui1/index.shtml
http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-ecgui2/index.shtml
http://www-900.ibm.com/developerWorks/cn/linux/opensource/os-ecgui3/index.shtml