作者:梁祺 ([email protected])
来自:http://www.benisoft.net/day3/index.html
今天我们来看一下TreeViewer,同样是使用“Plug-in with a view”模版,不过在向导的最后一页改用Tree viewer。
启动Eclipse前,先把eclipse.tutorial.day2的项目关闭,免得出现两个Sample View。启动Eclipse后, 找到Sample View,现在Sample View显示的是一个树状结构,有根节点,父节点,子节点组成。
双击Package Explorer View里的plug-in.xml,打开Plug-in Editor的Extensions子页, 你会发现内容和前面的例子一模一样。点击class打开Java类。
在Sample View里,TableViewer改成了TreeViewer了,多了一个DrillDownAdapter, DrillDownAdapter这里就不介绍了。
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = \ "eclipse.tutorial.day3.views.SampleView\";
private TreeViewer viewer;
private DrillDownAdapter drillDownAdapter;
private Action action1;
private Action action2;
private Action doubleClickAction;
还多了TreeObject和TreeParent两个内部类,这两个类比较简单,值得一提的是TreeObject实现IAdaptable接口。 对这个例子而言,这不是必须的。使用IAdaptable可以避免将真正的Model对象放在树上, 甚至可以更换Model对象而不用重新生成树。IAdaptable提供很高的灵活性。
private String name;
private TreeParent parent;
...
public Object getAdapter(Class key) {
return null;
}
}
ViewContentProvider实现了新接口ITreeContentProvider。 当需要显示TreeViewer的内容时,第一个调用的方法是getElement(),它接受参数parent, 这样根据不同的父节点parent,getElement()可以返回相应的子节点。 如果parent是getViewSite()返回的viewSite(就是viewer.setInput()时设置的对象),就返回根节点, 否则返回父节点的子节点。接下来getParent(),getChildren()和hasChildren()这三个方法必须行为一致, 否则随着TreeViewer使用,有可能碰到一些非常难以调试的问题,比如想要高亮选中某个节点,可能会不工作。
ITreeContentProvider {
private TreeParent invisibleRoot;
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object parent) {
if (parent.equals(getViewSite())) {
if (invisibleRoot== null) initialize();
return getChildren(invisibleRoot);
}
return getChildren(parent);
}
public Object getParent(Object child) {
if (child instanceof TreeObject) {
return ((TreeObject)child).getParent();
}
return null;
}
public Object [] getChildren(Object parent) {
if (parent instanceof TreeParent) {
return ((TreeParent)parent).getChildren();
}
return new Object[0];
}
public boolean hasChildren(Object parent) {
if (parent instanceof TreeParent)
return ((TreeParent)parent).hasChildren();
return false;
}
...
}
LabelProvider实现了getImage()方法, 为每个节点指定图标。
public String getText(Object obj) {
return obj.toString();
}
public Image getImage(Object obj) {
String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
if (obj instanceof TreeParent)
imageKey = ISharedImages.IMG_OBJ_FOLDER;
return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
}
}
Eclipse还提供了IColorProvider和IFontProvider使得我们可以为某些节点指定不同的颜色和字体。 IColorProvider提供getForeground(...)和getBackground(...)两个方法,分别用于指定前景色和背景色。 IFontProvider提供getFont(...)方法,指定显示时使用的字体。
public String getText(Object obj) {
return obj.toString();
}
public Image getImage(Object obj) {
String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
if (obj instanceof TreeParent)
imageKey = ISharedImages.IMG_OBJ_FOLDER;
return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);
}
public Font getFont(Object element) {
if (element instanceof TreeParent)
return getSite().getShell().getDisplay().getSystemFont();
return null;
}
public Color getForeground(Object element) {
if (element instanceof TreeParent)
return getSite().getShell().getDisplay().getSystemColor(SWT.COLOR_RED);
return null;
}
public Color getBackground(Object element) {
if (element instanceof TreeParent)
return getSite().getShell().getDisplay().getSystemColor(SWT.COLOR_CYAN);
return null;
}
}
到这里,我们看了如何创建TreeViewer,TreeViewer和TableViewer一样,关键就是Content Provider, Content Provider提供需要显示的对象,Label Provider指定如何显示这些对象。