java swing JTree树结点的增删改查

树结点

  1. javaSwing中使用JTree、TreeModel 来对创建树世界
  2. 树组件需要依赖顶层容器才能显示,意思是树组件,可以直接放到顶层容器中,Jtree 、TreeModel 这两个节点来开发计算机中的树
  3. Swing 使用 JTree 对象来代表一棵树,JTree树中结点可以使用 TreePath 来标识,该对象封装了当前结点及其所有的父结点。
  4. treepath里面包含了当前节点和其所有父节点
  5. treeNode【也是一个叶子节点】是一个接口,DefaultMutableTreeNode,是对接口的实现,我们使用这个,可以更好的使用其api
  6. jtree生成的树,不可编辑的,不可以添加、删除结点,不可改变结点数据,
 JTreesetEditable(true);

即可把这棵树变成可编辑的树(可以添加、删除结点,也可以改变结点数据) 。

  1. 获取当前选中节点方法有两种,通常用后者
1,通过JTree对象的某些方法,
	例如 TreePath getSelectionPath()等,得到一个TreePath对象,包含了从根结点到当前结点路径上的所有结点;
	调用TreePath对象的 Object getLastPathComponent()方法,得到当前选中结点
2,调用JTree对象的 Object getLastSelectedPathComponent() 方法获取当前被选中的结点
  1. JTree 专门提供了 一个 TreeSelectionModel 对象来保存该 JTree 选中状态的信息 。
  2. JTree组件背后隐藏了两个 model 对象 , TreeModel、TreeSelectionModel,
    其中TreeModel 用于保存该 JTree 的所有节点数据 , 而TreeSelectionModel 用于保存该 JTree的所有选中状态的信息 。
    程序可以改变 JTree 的选择模式 , 但必须先获取该 JTree 对应的 TreeSelectionMode1 对象 , 再调用该对象的 setSelectionMode(int mode),方法来设置该JTree的选择模式

在这里插入图片描述

JTree上每一个节点就代表一个TreeNode 对象,TreeNode本身是一个接口,里面定义了7个有关节点的方法,其中包括判断是否为叶子节点,有几个子节点(getChileCount())、父节点是什么(getparent()等,)在实际 开发中,一般不会直接实现此接口,而是采用Java所提供的DefaultMutableTreeModel类,此类用于实现MutableTreeNode接口,并提供其他许多实用的方法,MutableTreeNode本身也是一个接口,并且继承了TreeNode接口,此类主要是定义了一些节点的处理方式,比如添加节点(insert)、删除节点(remove())、设置节点(setUserObject())等。

案例:简单树

使用JTree和TreeNode完成下图效果:

在这里插入图片描述

package tree;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;
public class SimpleJTree extends JFrame
{
    public void init(){
        Container contentPane = getContentPane();
        //四个步骤
        //创建对象代表节点
        DefaultMutableTreeNode root =new DefaultMutableTreeNode("中国");
        DefaultMutableTreeNode guangDong =new DefaultMutableTreeNode("广东");
        DefaultMutableTreeNode guangXi =new DefaultMutableTreeNode("广西");
        DefaultMutableTreeNode foShan =new DefaultMutableTreeNode("佛山");
        DefaultMutableTreeNode shanTou =new DefaultMutableTreeNode("汕头");
        DefaultMutableTreeNode guiLin =new DefaultMutableTreeNode("桂林");
        DefaultMutableTreeNode nanNing =new DefaultMutableTreeNode("南宁");
        //组装节点之间的关系
        root.add(guangDong);
        root.add(guangXi);
        guangDong.add(foShan);
        guangDong.add(shanTou);
        guangXi.add(guiLin);
        guangXi.add(nanNing);
        //创建JTree对象
        JTree tree = new JTree(root);
        //把JTree放入到窗口中进行展示
        contentPane.add(tree);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }
    public static void main(String[] args) {
        new SimpleJTree().init();
    }
}

JTree的其他外观设置方法

tree.putClientProperty( "JTree.lineStyle", "None"):设置结点之间没有连接线
tree.putClientProperty("JTree.lineStyle" , "Horizontal"):设置结点之间只有水平分割线
tree.setShowsRootHandles(true):设置根结点有"展开、折叠"图标
tree.setRootVisible(false):隐藏根结点

DefaultMutableTreeNode其他成员方法

Enumeration breadthFirstEnumerationO/preorderEnumeration(): 按广度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
Enumeration depthFirstEnumerationO/postorderEnumeration(): 按深度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
DefaultMutableTreeNode getNextSibling(): 返回此结点的下一个兄弟结点 。
TreeNode getParent(): 返回此结点的父结点 。 如果此结点没有父结点,则返回nullTreeNode[] getPath(): 返回从根结点到达此结点的所有结点组成的数组。
DefaultMutableTreeNode getPreviousSibling(): 返回此结点的上一个兄弟结点。
TreeNode getRoot(): 返回包含此结点的树的根结点 。
TreeNode getSharedAncestor(DefaultMutableTreeNode aNode): 返回此结点和aNode最近的共同祖先 。
int getSiblingCount(): 返回此结点的兄弟结点数 。
boolean isLeaf(): 返回该结点是否是叶子结点 。
boolean isNodeAncestor(TreeNode anotherNode): 判断anotherNode是否是当前结点的祖先结点(包括父结点)boolean isNodeChild(TreeNode aNode): 如果aNode是此结点的子结点,则返回trueboolean isNodeDescendant(DefaultMutableTreeNode anotherNode): 如果 anotherNode 是此结点的后代,包括是此结点本身、此结点的子结点或此结点的子结点的后代,都将返回trueboolean isNodeRelated(DefaultMutableTreeNode aNode) : 当aNode和当前结点位于同一棵树中时返回 trueboolean isNodeSibling(TreeNode anotherNode): 返回anotherNode是否是当前结点的兄弟结点 。
boolean isRoot(): 返回当前结点是否是根结点 。
Enumeration pathFromAncestorEnumeration(TreeNode ancestor): 返回从指定祖先结点到当前结点的所有结点组成的枚举对象 。

案例:DefaultMutableTreeNode的成员方法练习

package Tree;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/22/2021/17:32
 * @Description:
 */
public class SimpleJTree extends JFrame
{
    public void init(){
        setTitle("函数的练习");
        Container contentPane = getContentPane();
        //四个步骤
        //创建对象代表节点
        DefaultMutableTreeNode root =new DefaultMutableTreeNode("中国");
        DefaultMutableTreeNode guangdong =new DefaultMutableTreeNode("广东");
        DefaultMutableTreeNode guangxi =new DefaultMutableTreeNode("广西");
        DefaultMutableTreeNode foShan =new DefaultMutableTreeNode("佛山");
        DefaultMutableTreeNode shantou =new DefaultMutableTreeNode("汕头");
        DefaultMutableTreeNode guilin =new DefaultMutableTreeNode("桂林");
        DefaultMutableTreeNode nanNing =new DefaultMutableTreeNode("南宁");
        //组装节点之间的关系
        root.add(guangdong);
        root.add(guangxi);
        guangdong.add(foShan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanNing);
        //创建JTree对象
        JTree tree = new JTree(root);
        //把JTree放入到窗口中进行展示

        /**
         * 方法展示:
         */
        System.out.println( "返回广东的父结点:"+ guangdong.getParent());    //广东的父节点是中国
        System.out.println( "广东的下一个兄弟节点是广西:"+ guangdong.getNextSibling());   //广西的下一个兄弟节点是广西

        System.out.println( "广东没有上一个兄弟节点:" +guangdong.getPreviousSibling());//广东没有上一个兄弟节点

        System.out.println("  //返回该节点所在的根节点:" + guangdong.getRoot());  //返回该节点所在的根节点

        System.out.println("返回两个节点的共同祖先:"+  guangdong.getSharedAncestor(guilin));   //
        System.out.println("该节点的兄弟数量:"+  guangdong.getSiblingCount());
        System.out.println("该节点是不是叶子节点:"+  guangdong.isLeaf());
        System.out.println("该节点是不是当前节点的祖先节点:"+  guangdong.isNodeAncestor(root));
        System.out.println("该节点是不是当前节点的儿子节点:"+  guangdong.isNodeChild(shantou));
        System.out.println("获取选中节点的索引getIndex(),root节点的guangxi的索引:"+root.getIndex(guangxi));
        System.out.println("getDepth()函数,获取root(中国)节点的深度为:" + root.getDepth());


        contentPane.add(new JScrollPane(tree));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }
    public static void main(String[] args) {
        new SimpleJTree().init();
    }
}


在这里插入图片描述

Object getLastSelectedPathComponent() 方法

获取当前被选中的结点

jtree的增删改查,需要用到Model对象,这个是JTree关联的模型对象,用于完成对象的增删改查,

添加兄弟结点,

添加子结点:直接调用当前结点的add方法把一个新结点添加到内部即可

删除结点:model.remove NodeFromParent(),这个方法

  1. 调用DefaultTreeModel数据模型有关增删改的一系列方法完成编辑,方法执行完后,会自动重绘JTree

案例:树节点增删改【重点】

使用JTree以及DefaultTreeModel、DefaultMutableTreeNode、TreePath完成下图效果:

package Tree;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 从南到北
 * @Date: 11/22/2021/16:32
 * @Description:
 *
 *  树节点的编辑,增删改查
 *
 */
public class EditTree extends JFrame {

    //定义几个初始结点
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
    DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
    DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
    DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
    DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
    DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
    DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");

    //定义按钮,完成操作
    JButton addSiblingBtn = new JButton("添加兄弟结点");
    JButton addChildBtn = new JButton("添加子结点");
    JButton deleteBtn = new JButton("删除结点");
    JButton editBtn = new JButton("编辑当前结点");

    JPanel panel = new JPanel();

    public EditTree(){
        setTitle("编辑树结点");

        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        JTree tree = new JTree(root);
        //设置JTree可编辑
        tree.setEditable(true);

        //获取JTree关联的数据模型TreeModel对象,里面有两个东西,所有jtree节点数据,jtree节点的选中状态信息
        // 如果要修改树的内容,就要调用这个对象
        //JTree关联的数据模型对象,treemodel是一个接口,得到一个实现类DefaultTreeModel
        //        TreeModel 是一个接口,DefaultTreeModel这个是对其的实现,
        DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); //强转为这个defaultTreeModel。是方便使用api

        /**
         * 添加兄弟结点
         */

        addSiblingBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //添加兄弟结点的逻辑
//                    1, 获取当前选中节点
                // DefaultMutableTreeNode这个是一个实现类
             DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
             //如果结点为空,则直接返回
                if (selectedNode == null){
                    return;
                }
//                    2,获取该选中结点的父结点
             DefaultMutableTreeNode parent = (DefaultMutableTreeNode)selectedNode.getParent();
                    //如果父结点为空,则直接返回
                if (parent==null){
                    return;
                }
                //                3,创建一个新结点
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");
    //                4,把新结点通过父结点进行添加
                //获取选中结点的索引
                int selectedIndex = parent.getIndex(selectedNode);
                //在选中位置插入新结点
                model.insertNodeInto(newNode,parent,selectedIndex);

    //                5,显示新结点
                //获取从根结点到新结点的所有结点,这个函数是返回从根节点到newNode新节点的路径
                TreeNode[] pathToRoot = model.getPathToRoot(newNode);

                //使用指定的结点数组创建TreePath
                TreePath treePath = new TreePath(pathToRoot);

                //显示指定的treePath
                tree.scrollPathToVisible(treePath); //将视野移动到这个新节点
                //6,重绘tree
                tree.updateUI();
            }
        });

        /**
         * 添加子节点
         */

        addChildBtn.addActionListener(e -> {    //兰姆达表达式写法,会更方便点
            //为选中节点添加子节点

            //1,获取选中结点
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
            if (selectedNode==null){
                return ;
            }

            //2,创建新结点
            DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");

            //3,把新节点添加到当前节点中

            //model.insertNodeInto(newNode,selectedNode,selectedNode.getChildCount());使用TreeModel的方法添加,不需要手动刷新UI
            selectedNode.add(newNode);//使用TreeNode的方法添加,需要手动刷新UI

            //4,显示新节点

            //显示新结点

            TreeNode[] pathToRoot = model.getPathToRoot(newNode);
            TreePath treePath = new TreePath(pathToRoot);
            tree.scrollPathToVisible(treePath);

            //5,重绘ui
            //手动刷新UI
            tree.updateUI();
        });


        /**
         * 删除节点
         */

        deleteBtn.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
            if (selectedNode!=null && selectedNode.getParent()!=null){
                //删的时候要找到其父节点才能删,所以说,最后的那个根节点,不能删
                model.removeNodeFromParent(selectedNode);
            }
        });

        /**
         * 编辑节点
         */
        //实现编辑结点的监听器
        editBtn.addActionListener(e -> {
            //获取当前选中节点的路径
            TreePath selectionPath = tree.getSelectionPath();
            //判断路径不为空,则设置最后一个节点可以编辑
            if (selectionPath!=null){
                //编辑选中结点
                tree.startEditingAtPath(selectionPath);
            }
        });

        panel.add(addSiblingBtn);
        panel.add(addChildBtn);
        panel.add(deleteBtn);
        panel.add(editBtn);

        //add(tree); //直接传tree不好,因为树不支持滚动条,所以会不显示之后的内容
        add(new JScrollPane(tree));
        add(panel, BorderLayout.SOUTH);  //上下
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
       new EditTree();
    }
}

在这里插入图片描述

监听结点事件

为JTree添加监听器:

  1. addTreeExpansionListener(TreeExpansionListener tel) : 添加树节点展开/折叠事件的监听器。
  2. addTreeSelectionListener(TreeSelectionListener tsl) : 添加树节点选择事件的监听器。

案例:打印选中结点路径

package Tree;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;


public class SelectJTree {
    JFrame jf = new JFrame("监听树的选择事件");
    JTree tree;

    DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
    DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
    DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
    DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
    DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
    DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
    DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");

    JTextArea eventTxt = new JTextArea(5, 20);

    public void init() {

        //通过add()方法建立父子层级关系
        guangdong.add(foshan);
        guangdong.add(shantou);
        guangxi.add(guilin);
        guangxi.add(nanning);
        root.add(guangdong);
        root.add(guangxi);

        tree = new JTree(root);

        //添加树节点,选择事件监听器

//        tree.addTreeSelectionListener(e -> {

//            if (e.getOldLeadSelectionPath()!=null){
//                eventTxt.append("原选中结点的路径:"+e.getOldLeadSelectionPath().toString()+"\n");
//            }
//                eventTxt.append("新选中结点的路径:"+e.getNewLeadSelectionPath().toString()+"\n");
//        });
//
//
//


        //设置选择模式,如果要选中节点,必须要有这个
        TreeSelectionModel selectionModel = tree.getSelectionModel();
        selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);  //单选模式

        //设置监听器
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent e) {
                //把当前选中节点的路径,显示到文本域中
                //e里面有事件源发生的所有信息
                TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
                //将treePath转换成字符串,显示到文本域中
                eventTxt.append(newLeadSelectionPath.toString()+"\n");
            }
        });

		// 设置节点选中监听器【重点】
        /**	上面那几句,其实可以用e.getpath()来代替的,结果是一样的,所以,建议用这种
         *      tree.addTreeSelectionListener(new TreeSelectionListener() {
         *             @Override
         *             public void valueChanged(TreeSelectionEvent e) {
         *                 System.out.println("当前被选中的节点: " + e.getPath());
         *             }
         *         });
         */




//        tree.setShowsRootHandles(true);
//        tree.setRootVisible(true);

        Box box = Box.createHorizontalBox();
        box.add(new JScrollPane(tree));
        box.add(new JScrollPane(eventTxt));

        jf.add(box);
        jf.pack();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);
    }

    public static void main(String[] args) {
        new SelectJTree().init();
    }
}

在这里插入图片描述

参考链接:
树结点的增删改:https://www.bilibili.com/video/BV1wh411d7it?p=85
Lambda表达式:https://www.bilibili.com/video/BV1h7411v7Mq?p=75

节点监听事件(打印节点路径):https://www.bilibili.com/video/BV1wh411d7it?p=86&spm_id_from=pageDriver

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在JTree中添加带有复选框的节点,可以使用JCheckBoxTree。JCheckBoxTree是一个自定义的Swing组件,它继承了JTree并添加了复选框功能。 以下是一个简单的示例,演示如何使用JCheckBoxTree: ```java import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; public class CheckBoxTreeExample extends JFrame { private JCheckBoxTree checkBoxTree; public CheckBoxTreeExample() { super("JCheckBoxTree Example"); // 创建根节点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root"); // 创建子节点 DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("Node 1"); DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("Node 2"); DefaultMutableTreeNode node3 = new DefaultMutableTreeNode("Node 3"); // 将子节点添加到根节点 root.add(node1); root.add(node2); root.add(node3); // 创建复选框 checkBoxTree = new JCheckBoxTree(new DefaultTreeModel(root)); // 将复选框添加到窗口 add(new JScrollPane(checkBoxTree), BorderLayout.CENTER); // 设置窗口大小和位置 setSize(300, 400); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { new CheckBoxTreeExample(); } } ``` 在这个示例中,我们创建了一个根节点和3个子节点,并将它们添加到根节点中。然后,我们使用JCheckBoxTree构造函数创建了一个复选框,并将其添加到窗口中。最后,我们设置了窗口的大小和位置,并将其设置为可见。 注意,JCheckBoxTree是一个自定义组件,您需要将其添加到您的项目中才能使用。您可以从互联网上下载可用的库或自己编写代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值