swing快速入门(四十四)拖动、编辑JTree结点

2024-01-15 09:36

本文主要是介绍swing快速入门(四十四)拖动、编辑JTree结点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

注释很详细,直接上代码

新增内容(源码细节知识点巨多,建议细看)

1.设置JTree可编辑
2.使用JTree关联的数据模型实现节点的增删改
3.鼠标拖动节点事件设计及处理方法
4.手动刷新视图与自动刷新的方法区别
5.自定位节点视图方法

源码 :

package swing41_50;import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;public class swing_test_42 {JFrame jFrame ;//定义JFrame对象JTree tree;//定义JTree对象DefaultTreeModel model;//JTree关联的数据模型对象//定义几个初始结点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("南宁");//定义需要被拖动的TreePathTreePath movePath;//定义按钮JButton addSiblingBtn = new JButton("添加兄弟结点");JButton addChildBtn = new JButton("添加子结点");JButton deleteBtn = new JButton("删除结点");JButton editBtn = new JButton("编辑当前结点");//初始化操作public void init(){//通过add()方法建立父子层级关系guangdong.add(foshan);guangdong.add(shantou);guangxi.add(guilin);guangxi.add(nanning);root.add(guangdong);root.add(guangxi);jFrame = new JFrame("可编辑结点的树");//创建JFrame对象tree = new JTree(root);//创建JTree对象//获取JTree关联的数据模型TreeModel对象model = (DefaultTreeModel) tree.getModel();//设置JTree可编辑(对一个节点三击中可以编辑)tree.setEditable(true);//创建鼠标事件监听器MouseListener mouseListener = new MouseAdapter() {//按下鼠标时,获得被拖动的结点路径@Overridepublic void mousePressed(MouseEvent e) {//如果需要唯一确定某个结点,则必须通过TreePath来获取//并且我们后面需要判断目标节点为移动节点的祖先节点,这种情况是不能移动的TreePath treePath = tree.getPathForLocation(e.getX(), e.getY());//获取当前点击的结点路径if (treePath!=null){//如果点击的结点路径存在movePath = treePath;//将当前点击结点的TreePath保存下来}}//松开树表示可以确定即将被拖入到的父结点@Overridepublic void mouseReleased(MouseEvent e) {TreePath treePath = tree.getPathForLocation(e.getX(), e.getY());//获取当前点击的结点路径if (treePath!=null && movePath!=null){//如果移动节点路径和目标节点路径都存在//判断目标路径是否是原路径的子代,如果是则目标路径比原路径短,目标节点是原节点的父代(不包括相等的情况)//成立则说明目标结点是被移动结点的子结点,也就无法移动if (movePath.isDescendant(treePath) && movePath!=treePath){//弹出警告框,提示无法移动JOptionPane.showMessageDialog(jFrame,"目标结点是被移动结点的子结点,无法移动!","非法移动",JOptionPane.WARNING_MESSAGE);}//判断目标节点路径和子节点路径是否为同一个节点//如果成立则说明并非相同节点if (movePath!=treePath){//add方法内部,先将该结点从原父结点删除,然后再把该结点添加到新结点中//获取目标节点和被移动节点//获取路径的最后一个结点,即上一次点击(选中)的节点DefaultMutableTreeNode tartParentNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();DefaultMutableTreeNode moveNode = (DefaultMutableTreeNode) movePath.getLastPathComponent();tartParentNode.add(moveNode);//添加子结点(将移动节点作为子节点添加到目标节点中)movePath=null;//清空移动节点tree.updateUI();//更新UI}}}};//为JTree添加鼠标监听器tree.addMouseListener(mouseListener);//创建JPanel对象JPanel panel = new JPanel();addSiblingBtn.addActionListener(e -> {//添加兄弟结点//获取选中结点DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();//如果结点为空,则直接返回if (selectedNode==null){return;}//获取该选中结点的父结点DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();//如果父结点为空,则直接返回if (parent==null){return;}//创建一个新结点DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");//获取选中结点在父节点中的索引//因为我们需要插在选中节点的前面int selectedIndex = parent.getIndex(selectedNode);//在选中位置前面插入新结点(如果想要后面则将selectedIndex+1即可)model.insertNodeInto(newNode,parent,selectedIndex);//----------显示新结点---------------// 这里的显示新节点并非是刷新界面,因为model方法会自动刷新//而是为了自动滚动以显示新结点//获取从根结点到新结点的所有结点TreeNode[] pathToRoot = model.getPathToRoot(newNode);//使用指定的结点数组创建TreePathTreePath treePath = new TreePath(pathToRoot);//显示指定的treePath//这个方法的作用是JTree 组件会自动滚动以确保指定路径的节点可见(如果树比较长视图显示不下的情况下有效果)tree.scrollPathToVisible(treePath);});//添加兄弟结点panel.add(addSiblingBtn);addChildBtn.addActionListener(e -> {//获取选中结点DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();if (selectedNode==null){//如果结点为空,则直接返回return ;}//创建新结点DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");//使用TreeModel的方法添加,不需要手动刷新UI//model.insertNodeInto(newNode,selectedNode,selectedNode.getChildCount());//使用TreeNode的方法添加,需要手动刷新UIselectedNode.add(newNode);//显示新结点TreeNode[] pathToRoot = model.getPathToRoot(newNode);TreePath treePath = new TreePath(pathToRoot);tree.scrollPathToVisible(treePath);//手动刷新UItree.updateUI();});panel.add(addChildBtn);//添加子结点deleteBtn.addActionListener(e -> {//获取选中结点DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();//如果结点存在且存在父结点//有小伙伴要问了,为什么还要判断有没有父节点,因为根节点不能删,否则会报错if (selectedNode!=null && selectedNode.getParent()!=null){//删除选中结点model.removeNodeFromParent(selectedNode);}});//删除结点panel.add(deleteBtn);//实现编辑结点的监听器editBtn.addActionListener(e -> {//获取选中结点的路径TreePath selectionPath = tree.getSelectionPath();if (selectionPath!=null){//如果选中结点不为空//编辑选中结点tree.startEditingAtPath(selectionPath);}});panel.add(editBtn);//编辑结点jFrame.add(new JScrollPane(tree));//给树添加滚动条jFrame.add(panel, BorderLayout.SOUTH);//添加按钮在南侧jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口关闭时退出程序jFrame.pack();//自动调整窗口大小jFrame.setVisible(true);//显示窗口}public static void main(String[] args) {//启动程序new swing_test_42().init();}
}

演示效果:

在这里插入图片描述

这篇关于swing快速入门(四十四)拖动、编辑JTree结点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608445

相关文章

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

Python FastAPI入门安装使用

《PythonFastAPI入门安装使用》FastAPI是一个现代、快速的PythonWeb框架,用于构建API,它基于Python3.6+的类型提示特性,使得代码更加简洁且易于绶护,这篇文章主要介... 目录第一节:FastAPI入门一、FastAPI框架介绍什么是ASGI服务(WSGI)二、FastAP

Spring AI与DeepSeek实战一之快速打造智能对话应用

《SpringAI与DeepSeek实战一之快速打造智能对话应用》本文详细介绍了如何通过SpringAI框架集成DeepSeek大模型,实现普通对话和流式对话功能,步骤包括申请API-KEY、项目搭... 目录一、概述二、申请DeepSeek的API-KEY三、项目搭建3.1. 开发环境要求3.2. mav

Python如何快速下载依赖

《Python如何快速下载依赖》本文介绍了四种在Python中快速下载依赖的方法,包括使用国内镜像源、开启pip并发下载功能、使用pipreqs批量下载项目依赖以及使用conda管理依赖,通过这些方法... 目录python快速下载依赖1. 使用国内镜像源临时使用镜像源永久配置镜像源2. 使用 pip 的并

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景