TreeViewer構建步驟
TreeViewer中主要通過內容提供器(ITreeContentProvider)和標簽提供器 (ILabelProvider)組織樹節點的內容和顯示的信息。TreeViewer的構建步驟如下。
1. 創建TreeViewer對象,例如“TreeViewer tv = new TreeViewer(composite);”。
2. 設定內容管理器,例如“tv.setContentProvider(new FileTreeContentProvider()); ”。
3. 設定標簽提供器,例如“tv.setLabelProvider(new FileTreeLabelProvider());”。
4. 設定TreeViewer的輸入數據,例如“tv.setInput("root");”(用戶可以通過輸入數 據構建樹)。
TreeViewer內容提供器
TreeViewer的內容提供器(ITreeContentProvider)構建樹中比較復雜的部分,它為樹的 顯示提供了內容,內容提供器要實現的方法如下。
1. getElements
此函數定義為“public Object[] getElements(Object inputElement);”,當程序開始 構建樹時,首先調用getElements返回一個對象的數組,此數組對象表示當前樹的根節點, inputElement參數為TreeViewer的輸入(setInput的輸入數據)。
2. hasChildren
此函數定義為“public boolean hasChildren(Object element);”,當TreeViewer顯示 一個節點後,會調用hasChildren函數判斷當前節點是否有子節點,如果有子節點則顯示“+ ”,element參數為要判斷是否有子節點的節點。
3. getChildren
此函數定義為“public Object[] getChildren(Object parentElement);”,當用戶選擇 節點打開子節點時,會調用getChildren函數返回下一層子節點,parentElement參數為選擇 的節點。
4. getParent
此函數定義為“public Object getParent(Object element);”,可以通過此方法返回 element的父節點。
5. inputChanged
此函數定義為“public void inputChanged(Viewer viewer, Object oldInput, Object newInput);”,當輸入改變時調用此方法。
6. dispose
此函數定義為“public void dispose();”,當樹銷毀時被調用。
其中,getElements、hasChildren和getChildren是常用的方法,用戶通過重寫這幾個方 法構建一棵樹,過程如下:通過getElements方法得到根,再通過hasChildren判斷根下是否 有子節點,如果有子節點,可以通過getChildren得到所有的子節點。如例程1為 ITreeContentProvider接口的一個簡單實現。
例程1 FileTreeContentProvider.java
class FileTreeContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object arg0) {
//返回樹的下一級節點
return ((File) arg0).listFiles();
}
public Object getParent(Object arg0) {
//返回樹的上一級節點
return ((File) arg0).getParentFile();
}
public boolean hasChildren(Object arg0) {
Object[] obj = getChildren(arg0);
//判斷樹是否有下一級節點,true為在節點顯示"+"信息
return obj == null ? false : obj.length > 0;
}
public Object[] getElements(Object arg0) {
//打印出樹的輸入信息,通常用戶可以通過輸入信息構建樹
System.out.println(arg0);
// File.listRoots()作為樹的根節點
return File.listRoots();
}
上例內容提供器通過文件系統獲得樹的輸入內容,從而使用戶構造的樹能顯示磁盤文件的 樹結構。
在TreeViewer中,通過標簽提供器(ILabelProvider)來顯示節點的相關信息,包括顯示 內容和圖標。
ILabelProvider主要實現getImage和getText函數。當TreeViewer得到一個節點後會通過 getText得到此節點的顯示文本,通過getImage方法得到節點的顯示圖標,代碼如例程2所示 。
例程2 ViewLabelProvider.java
class ViewLabelProvider extends ILabelProvider{
…
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);
}
…
}
TreeViewer實例
在TreeViewer實例中,一般還要定義樹節點的結構。本例中的File對象就能夠表示節點的 父子關系,代碼如例程3所示。
例程3 FileBrowserTreeViewer.java
/**
* 為了節省篇幅,把所有的import類注釋了
* 讀者可以通過ctrl+shift+o快捷鍵,自動引入所依賴的類
* */
public class FileBrowserTreeViewer extends ApplicationWindow {
public FileBrowserTreeViewer() {
super(null);
}
public void run() {
setBlockOnOpen(true);
open();
Display.getCurrent().dispose();
}
protected void configureShell(Shell shell) {
super.configureShell(shell);
shell.setText("File Tree");
shell.setSize(400, 400);
}
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
// 父容器分一列顯示
composite.setLayout(new GridLayout(1, false));
Button preserveCase = new Button(composite, SWT.CHECK);
preserveCase.setText("&Preserve case");
final TreeViewer tv = new TreeViewer(composite);
// 讓樹組件兩端對齊
tv.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
// 添加內容管理器
tv.setContentProvider(new FileTreeContentProvider());
// 添加標簽管理器
tv.setLabelProvider(new FileTreeLabelProvider());
// 設置treeviewer的輸入
tv.setInput("root"); // pass a non-null that will be ignored
preserveCase.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
boolean preserveCase = ((Button) event.widget).getSelection();
FileTreeLabelProvider ftlp = (FileTreeLabelProvider) tv
.getLabelProvider();
ftlp.setPreserveCase(preserveCase);
}
});
return composite;
}
public static void main(String[] args) {
new FileBrowserTreeViewer().run();
}
}
//定義內容提供器
class FileTreeContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object arg0) {
//返回樹的下一級節點
return ((File) arg0).listFiles();
}
public Object getParent(Object arg0) {
//返回樹的上一級節點
return ((File) arg0).getParentFile();
}
public boolean hasChildren(Object arg0) {
Object[] obj = getChildren(arg0);
//判斷樹是否有下一級節點,true為在節點顯示"+"信息
return obj == null ? false : obj.length > 0;
}
public Object[] getElements(Object arg0) {
//打印出樹的輸入信息,通常用戶可以通過輸入信息構建樹
System.out.println(arg0);
// File.listRoots()作為樹的根節點
return File.listRoots();
}
public void dispose() {
}
public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
}
}
//定義標簽提供器
class FileTreeLabelProvider implements ILabelProvider {
private List listeners;
private Image file;
private Image dir;
boolean preserveCase;
public FileTreeLabelProvider() {
listeners = new ArrayList();
try {
//添加文件和目錄的圖標
file = new Image(null, new FileInputStream("icons/file.gif"));
dir = new Image(null, new FileInputStream("icons/directory.gif"));
} catch (FileNotFoundException e) {
}
}
public void setPreserveCase(boolean preserveCase) {
this.preserveCase = preserveCase;
//觸發事件,重新得到顯示標簽
LabelProviderChangedEvent event = new LabelProviderChangedEvent(this);
for (int i = 0, n = listeners.size(); i < n; i++) {
ILabelProviderListener ilpl = (ILabelProviderListener) listeners
.get(i);
ilpl.labelProviderChanged(event);
}
}
public Image getImage(Object arg0) {
//返回目錄或文件的圖標
return ((File) arg0).isDirectory() ? dir : file;
}
public String getText(Object arg0) {
String text = ((File) arg0).getName();
if (text.length() == 0) {
text = ((File) arg0).getPath();
}
//返回目錄或文件的文件名
return preserveCase ? text : text.toUpperCase();
}
public void addListener(ILabelProviderListener arg0) {
//添加監聽器
listeners.add(arg0);
}
public void dispose() {
if (dir != null)
dir.dispose();
if (file != null)
file.dispose();
}
public boolean isLabelProperty(Object arg0, String arg1) {
return false;
}
public void removeListener(ILabelProviderListener arg0) {
//刪除監聽器
listeners.remove(arg0);
}
}
以上代碼中,在主窗口上添加了TreeViewer組件,在樹中顯示當前磁盤和文件結構。另外 可以通過“Preserve case”復選按鈕選擇是為原有顯示文本還是全部大寫顯示文本,程序運 行效果如圖1所示。
圖1 TreeViewer組件
TreeViewer的功能比較強大,在復雜的應用可以用它代替SWT的Tree組件,實現樹的完美 展現。
上例中文件“icons/file.gif”和目錄“icons/directory.gif”的圖片沒有加入,讀者 可以加入相應的顯示圖片,圖片的位置為相對於當前工程根目錄的相對路徑。