简介
JFace 是一个 UI 工具类集,用于处理许多通用 UI 编程任务。 JFace 无论是从 API 或其实现都是 Window-System- Independent (视窗系统无关)的,设计与 SWT 共同工作而并非完全替代。 JFace 是基于 SWT 的 Java 应用程序框架。其目标是提供一组可重用的组件,来简化以 Java 实现的 GUI 程序的编写。虽然 JFace 与 Eclipse 运行时核心有一些联系 ,但是提取 JFace 和 SWT 使用到非基于 Eclipse 运行时的独立 Java 程序还是相当直截了当的。
使用 JFace 开发 UI 程序必须使用 Eclipse PDE (Plug-in Development Environment) 支持,开发程序必须导入依赖的类库包括:
org.eclipse.core.commands_<version info>.jar
org.eclipse.equinox.commands_<version info>.jar
org.eclipse.osgi_<version info>.jar
org.eclipse.jface_<version info>.jar
org.eclipse.swt.win32.win32.x86_<version info>.jar
org.eclipse.ui.workbench_<version info>.jar
其中 org.eclipse.ui.workbench 并非 JFace 必须的类库,但其中包含很多有用的 Dialog ,一般添加。
TreeViewer 类
JFace 中提供了 TreeViewer 组件,用 TreeViewer 来表示树型结构对象的显示。 TreeViewer 功能比较强,它能定义节点、节点的显示标签、显示图标以及响应事件等信息。
java.lang.Object
org.eclipse.jface.viewers.Viewer
org.eclipse.jface.viewers.ContentViewer
org.eclipse.jface.viewers.StructuredViewer
org.eclipse.jface.viewers.ColumnViewer
org.eclipse.jface.viewers.AbstractTreeViewer
org.eclipse.jface.viewers.TreeViewer
TreeViewer 类主要通过内容提供器( ITreeContentProvider )和标签提供器( ILabelProvider )组织树节点的内容和显示的信息。 TreeViewer 通过 setContentProvider 方法设置内容提供器,这个方法继承自 AbstractTreeViewer ,通过 setLabelProvider 方法设置标签提供器,这个方法继承自 ColumnViewer 。 TreeViewer 类的使用主要围绕内容和标签提供器两个类来进行。
TreeViewer 的构建步骤如下:
1. 创建 TreeViewer 对象;
2. 设定内容管理器 setContentProvider ;
3. 设定标签提供器 setLabelProvider ;
4. 设定 TreeViewer 的输入数据 setInput ;
ITreeContentProvider 接口
继承关系:
IContentProvider
IStructuredContentProvider
org.eclipse.jface.viewers.ITreeContentProvider
方法摘要 | |
|
|
| |
|
|
从接口 org.eclipse.jface.viewers.IStructuredContentProvider 继承的方法 | |
从接口 org.eclipse.jface.viewers.IContentProvider 继承的方法 | |
ITreeContentProvider 为树的显示提供了内容,通过 getElements 方法得到树根,再通过 hasChildren 判断根下是否有子节点,如果有子节点,可以通过 getChildren 得到所有的子节点。
ILabelProvider 接口
继承关系:
org.eclipse.jface.viewers.IBaseLabelProvider
org.eclipse.jface.viewers.ILabelProvider
方法摘要 | |
| |
| |
从接口 org.eclipse.jface.viewers.IBaseLabelProvider 继承的方法 | |
ILabelProvider 主要实现 getImage 和 getText 函数,当 TreeViewer 得到一个节点后会通过 getText 得到此节点的显示文本,通过 getImage 方法得到节点的显示图标。
TreeViewer 例程
设计框架
设计一个实验管理目录的 TreeViewer ,模型结构如下:
包括下列类的层次结构:
树根
用户(名称,用户目录)
样品
实验
处理
树根下可以有多个用户,每个用户下可以有多个样品,每个样品下可以有多个实验,每个实验中可以包括多个实验数据的处理结果,根据这种组织模式,我们来创建类。
首先,创建一个基本的 Hello RCP 程序(不带 Activator ,即不勾选创建 RCP 过程中的 Activator 选项)。在 plugin.xml 中创建一个新的 org.eclipse.ui.views 扩展点,并新建一个 view ,命名其类名称为 cn.eclipsercp.jface.treeviewer.test.ViewPart1 ,继承自 org.eclipse.ui.part.ViewPart ,增加成员变量 ID=” “ cn.eclipsercp.jface.treeviewer.test.ViewPart1” , 然后修改 Perpective 代码如下:
public void createInitialLayout(IPageLayout layout) {
layout.setEditorAreaVisible( false );
layout.addView(ViewPart1. ID , SWT. LEFT , 1.0f, layout.getEditorArea());
}
运行程序:
模型实现
设计所有树上节点的基类 Node 如下:
public class Node {
String name ;
Node parent ;
List<Node> children = new ArrayList<Node>(10);
Node() {}
Node(Node parent) {
this .setParent(parent);
}
public String getName() {
return name ;
}
public void setName(String name) {
this . name = name;
}
public Node getParent() {
return parent ;
}
public void setParent(Node parent) {
this . parent = parent;
}
public void addChild(Node child) {
child.setParent( this );
children .add(child);
}
public void removeChild(Node child) {
children .remove(child);
}
public List<Node> getChildren() {
return children ;
}
}
主要包括 parent , children 和 Name 等私有成员变量,以及访问的 setter 和 getter 方法,通过一个 List 来保存该 Node 的所有子节点。
然后分别在此类的基础上继承得到 User (用户), Sample (样品), Experiment (实验), Process (处理)等类型,为了简单,这些类只是继承 Node 类即可,最后定义一个单例模式的 RootNode :
public class RootNode extends Node {
private static RootNode root = null ;
private RootNode() {}
public static synchronized RootNode getRootNode() {
if ( root == null ) {
root = new RootNode();
root .setParent( null );
root .initRootNode();
}
return root ;
}
private void initRootNode() {
User user;
Sample sample1,sample2;
Experiment expr1,expr2;
Process proc1,proc2;
user = new User();
user.setName( "Zhang" );
root .addChild(user);
user = new User();
user.setName( "Yang" );
sample1 = new Sample();
sample1.setName( "Sample1" );
sample2 = new Sample();
sample2.setName( "Sample2" );
user.addChild(sample1);
user.addChild(sample2);
expr1 = new Experiment();
expr1.setName( "Exp1" );
expr2 = new Experiment();
expr1.setName( "Exp2" );
sample2.addChild(expr1);
sample2.addChild(expr2);
proc1 = new Process();
proc2 = new Process();
proc1.setName( "Proc1" );
proc2.setName( "Proc2" );
expr2.addChild(proc1);
expr2.addChild(proc2);
root .addChild(user);
user = new User();
user.setName( "Wang" );
root .addChild(user);
}
}
连接模型与 TreeViewer
模型与 TreeViewer 之间进行连接主要是依靠 ContentProvider 和 LabelProvider 两个接口,分别通过两个类实现这些接口中的方法,然后在 ViewPart1 的 CreateControl 方法中创建 TreeViwer ,并设置他的内容提供器和标签提供器:
public class ViewPart1 extends ViewPart {
public static final String ID = "cn.eclipsercp.jface.treeviewer.test.ViewPart1" ;
Node root ;
TreeViewer tv ;
public ViewPart1() {
// TODO Auto-generated constructor stub
}
@Override
public void createPartControl(Composite parent) {
FillLayout fillLayout = new FillLayout(SWT. VERTICAL );
parent.setLayout(fillLayout);
tv = new TreeViewer(parent);
tv .setContentProvider( new TVContentProvider());
tv .setLabelProvider( new TVLabelProvider());
root = RootNode.getRootNode ();
tv .setInput( root );
}
@Override
public void setFocus() {
// TODO Auto-generated method stub
}
}
内容提供器:
public class TVContentProvider implements ITreeContentProvider {
@Override
public Object[] getChildren(Object parentElement) {
return ((Node) parentElement).getChildren().toArray();
}
@Override
public Object getParent(Object element) {
return ((Node) element).getParent();
}
@Override
public boolean hasChildren(Object element) {
return (((Node) element).getChildren().size() > 0);
}
@Override
public Object[] getElements(Object inputElement) {
return ((Node) inputElement).getChildren().toArray();
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// TODO Auto-generated method stub
}
}
标签提供器:
public class TVLabelProvider implements ILabelProvider {
private Map<ImageDescriptor, Image> imageCache = new HashMap<ImageDescriptor, Image>(20);
@Override
public Image getImage(Object element) {
ImageDescriptor descriptor = null ;
if (element instanceof User) {
descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (
Application. ID , "icons/alt_window_16.gif" );
} else if (element instanceof Sample) {
descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (
Application. ID , "icons/alt_window_16.gif" );
} else if (element instanceof Experiment) {
descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (
Application. ID , "icons/alt_window_16.gif" );
} else if (element instanceof cn.eclipsercp.jface.treeviewer.test.model.Process) {
descriptor = AbstractUIPlugin.imageDescriptorFromPlugin (
Application. ID , "icons/alt_window_16.gif" );
}
else {
throw unknownElement(element);
}
//obtain the cached image corresponding to the descriptor
Image image = (Image) imageCache .get(descriptor);
if (image == null ) {
image = descriptor.createImage();
imageCache .put(descriptor, image);
}
return image;
}
@Override
public String getText(Object element) {
String text;
if (element instanceof RootNode)
text= "root" ;
else if (element instanceof User)
text=((User)element).getName();
else if (element instanceof Sample)
text=((Sample)element).getName();
else if (element instanceof Experiment)
text=((Experiment)element).getName();
else if (element instanceof cn.eclipsercp.jface.treeviewer.test.model.Process)
text=((cn.eclipsercp.jface.treeviewer.test.model.Process)element).getName();
else
text=((Node)element).getName();
return text;
}
@Override
public void addListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public boolean isLabelProperty(Object element, String property) {
// TODO Auto-generated method stub
return false ;
}
@Override
public void removeListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
}
protected RuntimeException unknownElement(Object element) {
return new RuntimeException( "Unknown type of element in tree of type " + element.getClass().getName());
}
}
运行程序:
添加选择事件
在 ViewPart1 的 CreateControl 方法中,为 TreeViewer 成员变量 tv 增加选中节点的事件,通过 System.out.println 输出来表达事件的行为:
tv .addSelectionChangedListener( new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
// if the selection is empty clear the label
if (event.getSelection().isEmpty()) {
System. out .println( "Selected Nothing" );
return ;
}
if (event.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) event
.getSelection();
StringBuffer selected = new StringBuffer();
for (Iterator iterator = selection.iterator(); iterator
.hasNext();) {
Object element = (Node) iterator.next();
String value = ((Node)element).getName();
selected.append(value);
selected.append( ", " );
}
// remove the trailing comma space pair
if (selected.length() > 0) {
selected.setLength(selected.length() - 2);
}
System. out .println(selected.toString());
}
}
参考文献
1. http://www.eclipse.org/articles/Article-TreeViewer/TreeViewerArticle.htm