JTree--樹(基本使用)
JTree也是一個分層顯示數據的組件,它在Swing里復雜度算是中等,涉及的類不是很多,也沒有復雜的UI,所以單獨對一個樹來說,構造和渲染都不難,對于樹的操作比較麻煩的是拖拽和與其他組件數據交互.
對于JTree有幾個比較重要的類和接口: TreeMode是一個接口,用來構建樹的模型,實現這個接口之后我們可以把一些比較另類的組件抽象成一棵樹,TreeTable就是這個原理實現的;TreeNode是一個接口,代表樹的節點,DefaultMutableTreeNode是該接口的一個實現,我們一般構建樹使用它就可以了,當然也可以繼承它添加新的功能,或者實現TreeNode把節點變成其它組件; TreePath是一個類,負責節點到根的路徑,一般不需要我們來修改; TreeSelectionModel是一個接口,表示樹選擇組件的當前狀態,只是使用皆可以了,一般除非做很大的改動,否則不需要修改這個類;還有就是TreeCellRenderer和TreeCellEditor了,它們是樹的渲染器,實現特殊效果都需要實現它們;還有就是TreeUI了,樹的UI比較死板,很少需要修改.
由上面類和接口可以,樹還是一個不是很復雜的組件的,除了基本使用外,我們一般會用到的也就是對Cell進行渲染,替換樹的節點圖片,或者給節點加個CheckBox這些了.
先看樹的簡單使用,Sun官方給我們提供了例子:

這個例子只是簡單的構建一棵樹:
// Create the root nodes.
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
"The Java Series");
//add node
createNodes(top);
// Create a tree that allows one selection at a time.
tree = new JTree(top);
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
當然我們也可以先創建樹,再設置數據,這都是JTree的構造函數,本質上是沒區別的,最終JTree也是通過setModel設置數據的:
tree = new JTree();
tree.setModel(treeModel);
構造完樹之后還要把樹放在JScollPanel上,否則樹顯示會有問題:
// Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
到此為止,樹就完成了,當然Sun也提供了許多方法便捷于我們操作樹:
取得根節點:
// get the tree root node
TreeNode rootNode = (TreeNode)tree.getModel().getRoot();
取得樹的數據模型:
// get the tree model.
DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
取得樹的某一個節點的位置:
// get tree node path.
TreePath nodePath = new TreePath(treeModel.getPathToRoot(node));
設置節點的展開可見和選擇:
//select the node.
tree.setSelectionPath(nodePath);
// Ensures that the node identified by path is currently viewable.
tree.makeVisible(nodePath);
展開后滾動至節點可見:
// Makes sure all the path components display
tree.scrollPathToVisible(nodePath);
還有一個是設置鼠標點擊展開樹節點的(默認是雙擊,改成了0就是不可點擊):
// Sets the number of mouse clicks before a node will expand or close.
tree.setToggleClickCount(1);
另外就是一個設置Cell的高度的,但這個方法我們一般不用,大多時候是在Renderer里設置的,因為這樣設置可能有UI問題:
// Sets the height of each cell, in pixels.
tree.setRowHeight(15);
其它還有很多,因為JTree繼承JComponent,所以它有父類的所有方法,我們通過setXXX和getXXX就可以設置了.
說完基本的設置之后,說一下JTree的事件:
JTree繼承JComponent,所以它有JComponent的事件,但我們一般只關注鼠標的鍵盤的:
// add mouse listener
tree.addMouseListener(this);
// add key listener
tree.addKeyListener(this);
然后是JTree獨有的事件:
tree.addTreeExpansionListener(this);
tree.addTreeWillExpandListener(this);
tree.addTreeSelectionListener(this);
分別是樹節點展開(折疊)、樹節點將要展開(折疊)和樹節點選擇事件,我們一般用的多的是addTreeExpansionListener和addTreeSelectionListener事件:
事件處理都不是很復雜,增加監聽后實現方法就可以了,需要注意的是TreeSelectionListener和MouseListener,它們有事件重疊的地方:但在樹的節點點擊鼠標左鍵時觸發這兩個事件,點擊右鍵時觸發鼠標事件,所以這兩個事件都做監聽時,處理一定要注意:
先看TreeSelectionListener的處理:
@Override
publicvoid valueChanged(TreeSelectionEvent event) {
然后可以取得TreePath,之后取得Node
// Returns the current lead path.
TreePath newPath = event.getNewLeadSelectionPath();
TreePath oldPath = event.getOldLeadSelectionPath();
或者通過JTree取得Node
JTree tree = (JTree) event.getSource();
tree.getLastSelectedPathComponent();
再看MouseListener的處理:
@Override
publicvoid mouseClicked(MouseEvent e) {
鼠標組件場合比較簡單,因為這個時候節點被選中:
if (SwingUtilities.isLeftMouseButton(e)
&& e.getClickCount() == 1) {
// Returns the last path component
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
}
右鍵則要得出節點位置再處理:
if (SwingUtilities.isRightMouseButton(e)) {
// Returns the row for the specified location.
int selectRow = tree.getRowForLocation(e.getX(), e.getY());
// Returns the path for the node at the specified location.
TreePath selectPath = tree.getPathForLocation(e.getX(), e
.getY());
if (selectPath != null) {
// set select
tree.setSelectionPath(selectPath);
// get tree node.
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) selectPath.getLastPathComponent();
}
之后有了樹和選擇節點就可以做自己的業務邏輯了.
另外JTree的節點的增加、修改和刪除也需要看一下,如果我們使用DefaultTreeModel的話,這些操作都很簡單,通過它的insertNodeInto、
removeNodeFromParent、nodeChanged等方法就可以實現了,但是如果是我們自己實現的TreeModel,必須再做完數據的操作之后UpdateUI更新界面,
或者學習Sun的事件機制,觸發事件然后在View層更新畫面,一般都不推薦這么做,除非你的TreeModel的數據特別復雜,沒辦法使用DefaultTreeModel
這個數據容器,例如TreeTable.
到此,除了JTree的Renderer和Editor之外,只剩下JTree的取數據了.JTree的數據取得我們一般都是用遞歸,這兒寫個從任何節點遞歸其下所有的例子:
private List<TreeNode> treeNodeList = new ArrayList<TreeNode>();
publicvoid getChildNodeList(TreeNode treeNode) {
if (treeNode == null) {
thrownew RuntimeException("error treenode.");
}
if (treeNodeList == null) {
treeNodeList = new ArrayList<TreeNode>();
}
if (treeNode.getChildCount() >= 0) {
for (Enumeration<TreeNode> e = treeNode.children(); e
.hasMoreElements();) {
TreeNode childNode = (TreeNode) e.nextElement();
treeNodeList.add(childNode);
getChildNodeList(childNode);
}
}
}
最后我們看一個Renderer的例子,Sun官方提供的:

首先看它的Renderer實現,這個是直接繼承DefaultTreeCellRenderer
privateclass MyRenderer extends DefaultTreeCellRenderer {
然后復寫它的getTreeCellRendererComponent方法:
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
它的默認實現時一個JLabel,在里面我們就可以設置它的效果了,這里設置一個圖片:
setIcon(tutorialIcon);
當然我們也可以繼承其它組件,實現TreeCellRenderer接口,實現更多效果.
使用很簡單,直接使用JTree的setCellRenderer方法就可以了:
tree.setCellRenderer(new MyRenderer(tutorialIcon));
總結,基本樹的操作和呈現設置都這里就完成了,可以看出,樹還是比較簡單的,后面我預計還有兩個主題,一個是關于JTree的Renderer和Editor的,在那兒實現一棵樹的節點的圖片特性,可用與否,選擇隱藏等;另外就是關于樹的選擇框了,其實也是Renderer和Editor的使用,只不過為了邏輯和應用,做的更復雜.
posted on 2010-04-20 22:36 zeyuphoenix 閱讀(9813) 評論(0) 編輯 收藏 所屬分類: JTree的使用