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();}
}

演示效果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/623377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux环境中一次启动多个jar包,并且设置脚本开机自启

1、编写启动脚本 我们在通过jar启动项目时,有时候会比较多,启动会比较麻烦,需要编写shell脚本启动,将启动脚本存放在需要启动的jar包路径下。(文档存放在 /home/process_parent ) vim start.sh#! /bin/sh…

【python】11.文件和异常

文件和异常 实际开发中常常会遇到对数据进行持久化操作的场景,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于文件系统的知识,但是这里我们并不浪费笔墨介绍这个概念,请大…

动态规划算法的应用

动态规划算法的应用 LeetCode:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。 思考: /*** 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总…

为什么会被诊断为发作性睡病?

发作性睡病的诊断主要基于患者的症状和相关医学检查的结果。具体来说,医生会根据患者是否出现白天发作性嗜睡、猝倒、睡眠瘫痪和入睡前幻觉等症状来做出初步诊断。这些症状可能在不同的患者身上表现程度不同,但它们通常是发作性睡病的典型特征。 为了进…

Vue报错 Cannot find module ‘../../modules/es6.symbol‘解决办法

在进行webpack打包的时候,会出现Cannot find module XXX’的错误,找不到某个模块的错误,今天给出解决方法: 直接进行npm install重新打包;如果npm install重新打包之后,仍然出现这个问题,可以进…

NLP论文阅读记录 - 2021 | WOS 智能树提取文本摘要深度学习

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.前提三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 An Intelligent Tree Extractive Text Summarization Deep Learning …

迁移mysql8.x数据到monggodb数据库

因流量逐步增加随即数据库要从mysql换成monggodb,所以有了数据迁移的需求 首先需要导出mysql的数据,导出格式为.CSV的文件 使用navicat链接mysql数据库注意,需要使用拥有所有权限的用户 登录mysql mysql -u root -pZxcvbnm2024 CREATE USER …

vue3-类与样式绑定

Class 与 Style 绑定 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。 Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。 绑定cla…

工智能基础知识总结--朴素贝叶斯

什么是朴素贝叶斯 朴素贝叶斯是基于贝叶斯定理与特征条件独立假设的分类方法。 给定训练集 T = ( x 1 , y 1 ) , ( x 2 , y 2 ) ,

Python 点云处理总目录

一、点云滤波 原始点云包含过多噪点和冗余点,滤波和采样往往是点云预处理的必要步骤 1.滤波 直通滤波 统计滤波 半径滤波 2.采样 下采样抽稀 二、邻近搜索 如何组织点云快速获取当前点邻域范围,是面对海量点云保证处理速度的重要前提 3.KD树与八…

linux如何创建文件教程分享

在Linux中创建文件通常通过使用命令行完成。这里有几种不同的方法来创建一个新文件: 1. 使用 touch 命令 touch 命令是最简单的创建空文件的方式。这个命令将更新文件的访问和修改时间戳。如果指定的文件不存在,它将创建一个空文件。 touch newfile.t…

Python实现读取超100G的数据文件

前言 本文是该专栏的第42篇,后面会持续分享python的各种干货知识,值得关注。 在项目工作中,难免会遇到需要你通过python去读取100G甚至超过100G的数据文件。对于小数据的文件来说,相信很多同学都可以轻松解决。但对于大数据文件,类似读取100G的数据文件甚至会对电脑的性能…

实战指南:如何在Spring Boot中无缝整合Dubbo【四】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 实战指南:如何在Spring Boot中无缝整合Dubbo【四】 前言项目结构主项目(作为主pom)接口服务提供者properties文件实现类 服务消费者properties接口层 实现效果图 前言 微服务架构已经成为…

BUUCTFMisc (我flag呢???)

刚好,更完密码学,然后就到下一个对新手还算 “友好” 的地方了--->Misc(但他还是比密码学难) 找不出flag belike : 看了别人的找法以后be like: 这里我就来讲几道我觉得比较有意思的题目吧&…

python 字符串的详细处理方法

当前版本: Python 3.8.4 简介 字符串是由字符组成的序列,可以用单引号、双引号或三引号(单引号或双引号的连续使用)括起来。一般用来表示和处理文本信息,可以是字母、数字、标点符号以及其他特殊字符,用于…

CAN/CANFD数据记录仪汽车电子售后神器

CAN数据记录仪是一种用于采集和存储CAN总线数据的工具,广泛应用于汽车、轨道车辆、工业控制等大数据量且不易排查故障的系统中。它可以实时存储总线上的数据,方便后续的研究和分析。解决工程师售后难点。 在选择CAN数据记录仪时,需要根据实…

JavaScript基础05

1 - 作用域 1.1 作用域概述 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。 Ja…

结构化数据,非结构化数据,半结构化数据(AI问答)

结构化数据,非结构化数据,半结构化数据,请介绍一下 结构化数据、非结构化数据和半结构化数据是按照数据组织形式和复杂度进行区分的三大类型: 结构化数据: 结构化数据是指具有固定格式和预定义模式的数据,…

春节回家前,请一定给你的电脑装上KKView远程控制软件

马上春节了,电脑不能带回家,有时候要处理点意外的事情,怎么办?只要走之前,给你电脑装上KKView远程控制软件,就可以随时随地用手机或电脑控制你的工作电脑,远程办公、传文件、看摄像头都没问题。…

Spring全局异常处理

目录 概述依赖导入创建全局异常处理总结 概述 在Spring框架中,全局异常处理主要是通过ControllerAdvice(或其特化形式RestControllerAdvice)注解和ExceptionHandler注解来实现的。这种机制能够捕捉到控制器(Controller或RestCont…