JavaSwing_4.9: JTree(樹)

本文鏈接: http://blog.csdn.net/xietansheng/article/details/78079812

Java Swing 圖形界面開發(目錄)

1. 概述

官方JavaDocsApi: javax.swing.JTree

JTree,樹。將分層數據顯示爲樹狀輪廓的組件。

一顆樹由若干節點,通過層級關係組成,一個節點由TreeNode實例來表示,節點在樹中的位置(路徑)由TreePath實例來表示(定位)。

創建樹時,首先要創建一個根節點,然後創建第二層節點添加到根節點,繼續創建節點添加到其父節點,最終形成由根節點所引領的一棵樹,再由 JTree 數組件顯示出來。所有擁有子節點的節點可以自由展開或摺疊子節點。

TreeNode 是一個接口,創建節點對象時,通常使用已實現該接口的的 DefaultMutableTreeNode 類。

2. 節點: DefaultMutableTreeNode

DefaultMutableTreeNode表示一個節點,擁有對節點增刪改查等操作的豐富方法。DefaultMutableTreeNode 實現了 MutableTreeNode 接口,而 MutableTreeNode 接口繼承自 TreeNode 接口。

DefaultMutableTreeNode 構造方法:

/**
 * 參數說明:
 *     userObject: 節點的用戶對象(節點顯示的名稱)
 *     allowsChildren: 是否允許有子節點
 */
DefaultMutableTreeNode()

DefaultMutableTreeNode(Object userObject)

DefaultMutableTreeNode(Object userObject, boolean allowsChildren)

DefaultMutableTreeNode 常用方法:

// 添加一個子節點在末尾
void add(MutableTreeNode newChild);

// 在指定位置插入一個子節點
void insert(MutableTreeNode newChild, int childIndex) 

// 移除子節點
void remove(int childIndex);
void remove(MutableTreeNode aChild);
void removeAllChildren();

// 獲取子節點數量
int getChildCount();
// 獲取葉子節點的數量
int getLeafCount();

// 獲取指定索引位置的子節點
TreeNode getChildAt(int index);
// 獲取指定子節點之後的子節點
TreeNode getChildAfter(TreeNode aChild);
// 獲取指定子節點之前的子節點
TreeNode getChildBefore(TreeNode aChild);

// 判斷某節點是否爲此節點的子節點
boolean isNodeChild(TreeNode aNode);

// 獲取此節點的父節點,沒有父節點則返回 null
TreeNode getParent();

// 判斷此節點是否爲根節點
boolean isRoot();

// 判斷是否爲葉節點(沒有子節點即爲葉節點,則返回 true)
boolean isLeaf();

// 返回此節點上的級數,從根到此節點的距離。如果此節點爲根,則返回 0。
int getLevel();

// 返回從根到此節點的路徑。該路徑中第一個元素是根節點,最後一個元素是此節點。
TreeNode[] getPath();

// 遍歷子節點(只包括直接子節點,不包括孫節點)
Enumeration children();
// 按廣度優先的順序遍歷以此節點爲根的子樹(包含此節點下的所有節點)
Enumeration breadthFirstEnumeration();
// 按深度優先的順序遍歷以此節點爲根的子樹(包含此節點下的所有節點)
Enumeration depthFirstEnumeration();

// 設置節點的用戶對象(節點顯示的名稱)
void setUserObject(Object userObject);
// 獲取節點的用戶對象(節點顯示的名稱)
Object getUserObject();

3. 路徑: TreePath

TreePath表示某節點的路徑(從根節點到此節點),一般使用方式:

// 一個節點
DefaultMutableTreeNode node = ...;

// 獲取節點的路徑(從根節點到此節點沿路徑的所有節點集)
TreeNode[] pathNodes = node.getPath();

// 使用節點路徑集創建樹路徑
TreePath treePath = new TreePath(pathNodes);

/* 
 * 這裏得到的 treePath 表示的是樹中的一個路徑,可以定位到具體的節點,
 * 從而對該節點進行相關操作(展開/摺疊子節點等),詳見後面 JTree 的介紹。
 */

/* 樹路徑的其他常用方法 */

// 獲取此樹路徑上的所有節點,返回數組的元素爲節點對象
Object[] paths = treePath.getPath();

// 獲取此樹路徑上的節點數量
int nodeCount = treePath.getPathCount();

// 獲取此樹路徑表示的節點的父節點的樹路徑
TreePath parentPath = treePath.getParentPath();

// 判斷指定樹路徑是否爲此樹路徑的“子孫”樹路徑
boolean isDescendant = treePath.isDescendant(TreePath aTreePath);

4. 樹: JTree

JTree表示一個樹組件,負責把內存中構造的整顆結構樹顯示出來。因爲對於樹結構,只需要得到一個根節點,就相當於獲取到了整棵樹的應用,因此只需要把一顆樹的根節點傳遞給 JTree 便可顯示整棵樹。

JTree 實例的創建:

// 方式一: 指定一個根節點創建樹
JTree tree = JTree(TreeNode root);

// 方式二: 先創建一個樹模型(自定義樹模型或使用已實現的默認樹模型),再用指定樹模型創建樹
TreeModel treeModel = new DefaultTreeModel(TreeNode root);
JTree tree = JTree(treeModel);

// 方式三: 先創建一個空樹,在設置樹模型
JTree tree = JTree();
tree.setModel(TreeModel newModel);

JTree 對節點的操作:

// 通過行索引獲取指定行的樹路徑(這裏的行表示的是在 JTree 組件
// 內可以直接看到的行,即不包括已摺疊的,根節點行索引爲 0,如果
// 根節點展開,則根節點的直接第一個子節點行索引爲 1)。
TreePath getPathForRow(int row);
// 根據樹路徑獲取指定節點所在行索引
int getRowForPath(TreePath path);

// 根據在 JTree 組件內的座標獲取指定座標處所在的節點定位,
// 通過監聽鼠標點擊事件獲取到點擊座標,從而可利用此方法實現
// 監聽對節點的單擊或雙擊事件。
int getRowForLocation(int x, int y);
TreePath getPathForLocation(int x, int y);

// 展開指定節點(通過可視行索引或樹路徑定位目標節點)
void expandRow(int row);
void expandPath(TreePath path);

// 摺疊指定節點
void collapseRow(int row);
void collapsePath(TreePath path);

// 判斷指定節點是否處於展開狀態
boolean isExpanded(int row);
boolean isExpanded(TreePath path);

// 設置當前默認選中的節點(可多選)
void setSelectionRow(int row);
void setSelectionRows(int[] rows);
void setSelectionPath(TreePath path);
void setSelectionPaths(TreePath[] paths);

// 獲取當前選中的節點
int[] getSelectionRows();
TreePath getSelectionPath();
TreePath[] getSelectionPaths();

// 是否顯示根節點(默認顯示)
void setRootVisible(boolean rootVisible);

// 是否顯示根節點的句柄(默認不顯示)
void setShowsRootHandles(boolean newValue);

// 是否允許編輯節點
void setEditable(boolean flag);

JTree 自定義節點樣式(字體、圖標等):

// 首先,創建一個樹節點的渲染器
DefaultTreeCellRenderer render = new DefaultTreeCellRenderer();

// 設置節點 展開 和 摺疊 狀態顯示的圖標
render.setOpenIcon(Icon newIcon);
render.setClosedIcon(Icon newIcon);

// 設置葉子節點顯示的圖標
render.setLeafIcon(Icon newIcon);

// 設置節點字體,以及 選中 和 未選中 時的顏色
render.setFont(Font font);
render.setTextSelectionColor(Color newColor);
render.setTextNonSelectionColor(Color newColor);

// 設置節點 選中 和 未選中 時的背景顏色
render.setBackgroundSelectionColor(Color newColor);
render.setBackgroundNonSelectionColor(Color newColor);

// 最後,設置樹組件的節點渲染器
jTree.setCellRenderer(render);

JTree 對節點變化的監聽:

JTree tree = new JTree(rootNode);

/*
 * 節點展開/摺疊監聽器
 */
tree.addTreeExpansionListener(new TreeExpansionListener() {
    @Override
    public void treeExpanded(TreeExpansionEvent event) {
        System.out.println("展開的節點: " + event.getPath());
    }
    @Override
    public void treeCollapsed(TreeExpansionEvent event) {
        System.out.println("摺疊的節點: " + event.getPath());
    }
});

/*
 * 節點展開/摺疊監聽器(比上一個監聽器先執行)
 */
tree.addTreeWillExpandListener(new TreeWillExpandListener() {
    @Override
    public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
        System.out.println("展開的節點: " + event.getPath());
    }
    @Override
    public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
        System.out.println("摺疊的節點: " + event.getPath());
    }
});

/*
 * 節點被選中的監聽器
 */
tree.addTreeSelectionListener(new TreeSelectionListener() {
    @Override
    public void valueChanged(TreeSelectionEvent e) {
        // 獲取被選中的相關節點
        TreePath path = e.getPath();
        TreePath[] paths = e.getPaths();
        TreePath newLeadPath = e.getNewLeadSelectionPath();
        TreePath oldLeadPath = e.getOldLeadSelectionPath();
    }
});

// 節點增刪改監聽器
tree.getModel().addTreeModelListener(new TreeModelListener() {
    @Override
    public void treeNodesChanged(TreeModelEvent e) {
        System.out.println("節點改變: " + e.getTreePath());
    }
    @Override
    public void treeNodesInserted(TreeModelEvent e) {
        System.out.println("節點插入: " + e.getTreePath());
    }
    @Override
    public void treeNodesRemoved(TreeModelEvent e) {
        System.out.println("節點移除: " + e.getTreePath());
    }
    @Override
    public void treeStructureChanged(TreeModelEvent e) {
        System.out.println("結構改變: " + e.getTreePath());
    }
});

5. 代碼實例

package com.xiets.swing;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;

public class Main {

    public static void main(String[] args) {
        JFrame jf = new JFrame("測試窗口");
        jf.setSize(300, 300);
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        JPanel panel = new JPanel(new BorderLayout());

        // 創建根節點
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("中國");

        // 創建二級節點
        DefaultMutableTreeNode gdNode = new DefaultMutableTreeNode("廣東");
        DefaultMutableTreeNode fjNode = new DefaultMutableTreeNode("福建");
        DefaultMutableTreeNode shNode = new DefaultMutableTreeNode("上海");
        DefaultMutableTreeNode twNode = new DefaultMutableTreeNode("臺灣");

        // 把二級節點作爲子節點添加到根節點
        rootNode.add(gdNode);
        rootNode.add(fjNode);
        rootNode.add(shNode);
        rootNode.add(twNode);

        // 創建三級節點
        DefaultMutableTreeNode gzNode = new DefaultMutableTreeNode("廣州");
        DefaultMutableTreeNode szNode = new DefaultMutableTreeNode("深圳");

        DefaultMutableTreeNode fzNode = new DefaultMutableTreeNode("福州");
        DefaultMutableTreeNode xmNode = new DefaultMutableTreeNode("廈門");

        DefaultMutableTreeNode tbNode = new DefaultMutableTreeNode("臺北");
        DefaultMutableTreeNode gxNode = new DefaultMutableTreeNode("高雄");
        DefaultMutableTreeNode jlNode = new DefaultMutableTreeNode("基隆");

        // 把三級節點作爲子節點添加到相應的二級節點
        gdNode.add(gzNode);
        gdNode.add(szNode);

        fjNode.add(fzNode);
        fjNode.add(xmNode);

        twNode.add(tbNode);
        twNode.add(gxNode);
        twNode.add(jlNode);

        // 使用根節點創建樹組件
        JTree tree = new JTree(rootNode);

        // 設置樹顯示根節點句柄
        tree.setShowsRootHandles(true);

        // 設置樹節點可編輯
        tree.setEditable(true);

        // 設置節點選中監聽器
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent e) {
                System.out.println("當前被選中的節點: " + e.getPath());
            }
        });

        // 創建滾動面板,包裹樹(因爲樹節點展開後可能需要很大的空間來顯示,所以需要用一個滾動面板來包裹)
        JScrollPane scrollPane = new JScrollPane(tree);

        // 添加滾動面板到那內容面板
        panel.add(scrollPane, BorderLayout.CENTER);

        // 設置窗口內容面板並顯示
        jf.setContentPane(panel);
        jf.setVisible(true);
    }

}

結果展示:

result.gif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章