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

相关文章

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

MybatisX快速生成增删改查的方法示例

《MybatisX快速生成增删改查的方法示例》MybatisX是基于IDEA的MyBatis/MyBatis-Plus开发插件,本文主要介绍了MybatisX快速生成增删改查的方法示例,文中通过示例代... 目录1 安装2 基本功能2.1 XML跳转2.2 代码生成2.2.1 生成.xml中的sql语句头2