• P35 JTree树


    系统:Win10
    Java:1.8.0_333
    IDEA:2020.3.4
    Gitee:https://gitee.com/lijinjiang01/JavaSwing

    1.概述

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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());
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    5.代码实例

    import com.lijinjiang.beautyeye.BeautyEyeLNFHelper;
    import javax.swing.*;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.tree.DefaultMutableTreeNode;
    import java.awt.*;
    
    public class Demo01 {
        public static void main(String[] args) {
            try {
                BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.generalNoTranslucencyShadow;
                BeautyEyeLNFHelper.launchBeautyEyeLNF();
            } catch (Exception e) {
                e.printStackTrace();
            }
            JFrame frame = new JFrame("Demo01");
            frame.setSize(300, 300);
    
            JPanel panel = new JPanel(new BorderLayout());
    
            // 创建根节点
            DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("中国");
    
            // 创建二级节点
            DefaultMutableTreeNode node01 = new DefaultMutableTreeNode("北京");
            DefaultMutableTreeNode node02 = new DefaultMutableTreeNode("上海");
            DefaultMutableTreeNode node03 = new DefaultMutableTreeNode("广东");
            DefaultMutableTreeNode node04 = new DefaultMutableTreeNode("浙江");
    
            // 把二级节点作为子节点添加到根节点
            rootNode.add(node01);
            rootNode.add(node02);
            rootNode.add(node03);
            rootNode.add(node04);
    
            // 创建三级节点
            DefaultMutableTreeNode child01 = new DefaultMutableTreeNode("北京市");
    
            DefaultMutableTreeNode child02 = new DefaultMutableTreeNode("上海市");
    
            DefaultMutableTreeNode child03 = new DefaultMutableTreeNode("广州市");
            DefaultMutableTreeNode child04 = new DefaultMutableTreeNode("深圳市");
            DefaultMutableTreeNode child05 = new DefaultMutableTreeNode("佛山市");
    
            DefaultMutableTreeNode child06 = new DefaultMutableTreeNode("杭州市");
            DefaultMutableTreeNode child07 = new DefaultMutableTreeNode("宁波市");
    
            // 把三级节点作为子节点添加到相应的二级节点
            node01.add(child01);
    
            node02.add(child02);
    
            node03.add(child03);
            node03.add(child04);
            node03.add(child05);
    
            node04.add(child06);
            node04.add(child07);
    
            // 使用根节点创建树组件
            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);
    
            // 设置窗口内容面板并显示
            frame.add(panel);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    6.效果演示

    在这里插入图片描述

  • 相关阅读:
    《商业银行信息科技风险管理指引》
    [数据结构]~二叉树
    在.NET 6.0中使用不同的托管模型
    “MIME 媒体类型“用来标识网络传输内容的格式标准
    黑客技术(网络安全)自学2024
    【PTA】 浙江大学计算机与软件学院2021年考研复试上机题自测
    了解冒泡排序
    【Python爬虫】爬取2022软科全国大学排行榜
    逆波兰计算器的实现(思路分析) [数据结构][Java]
    C# 使用SpecFlow创建BDD测试用例
  • 原文地址:https://blog.csdn.net/qq_35132089/article/details/126900475