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.文件和异常

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

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 …

实战指南:如何在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数据记录仪时,需要根据实…

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

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

2024.1.15每日一题

LeetCode 82.删除排序链表中的重复元素 II 82. 删除排序链表中的重复元素 II - 力扣(LeetCode) 题目描述 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 示例…

docker安装部署Elasticsearch(ES)以及相关配置

Elasticsearch简介 mysql用作持久化存储,ES用作检索 基本概念:index库>type表>document文档 index索引(相当于MySQL的数据库) 动词:相当于mysql的insert 名词:相当于mysql的db Type类型&#xff…

Jenkins-自动化

定时构建 使用Cron表达式指定执行时间。 # 格式 # ┌──分(0 - 59) # │ ┌──时(0 - 23) # │ │ ┌──日(1 - 31) # │ │ │ ┌─月(1 - 12) # │ │ │ │ ┌─星期&#…

这本书没有一个公式,却讲透了数学的本质!

《数学的雨伞下:理解世界的乐趣》。一本足以刷新观念的好书,从超市到对数再到相对论,娓娓道来。对于思维空间也给出了一个更容易理解的角度。 作者:米卡埃尔•洛奈 原文完整版PDF:https://pan.quark.cn/s/019bf19c4981…

电子学会C/C++编程等级考试2023年09月(六级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:生日相同 在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的名字,出生月日。试找出所有生日相同的学生。 时间限制:1000 内存限制:65536 输入 第一行为整数n,表示有n个学生,n ≤ 180。此后每行包含一…

深入理解 go reflect - 要不要传指针

在我们看一些使用反射的代码的时候,会发现,reflect.ValueOf 或 reflect.TypeOf 的参数有些地方使用的是指针参数,有些地方又不是指针参数, 但是好像这两者在使用上没什么区别,比如下面这样: var a 1 v1 :…

AI教我学编程之C#类的基本概念(1)

前言 在AI教我学编程之C#类型 中,我们学习了C#类型的的基础知识,而类正是类型的一种. 目录 区分类和类型 什么是类? 什么是类型? 追问 实操 总结 区分类和类型 在 C# 中,类是类型的一种。C# 是一种面向对象的编程…

利用XSS漏洞打cookie

目录 1、为什么要打cookie? 2、怎样利用XSS来打cookie? 3、利用Bluelotus_xssReceiver平台来打cookie 4、利用beef-xss平台来打cookie 上一篇给大家介绍了xss漏洞的基础知识,在本篇章将会介绍和演示一下利用xss漏洞打cookie的演示&#x…

DAY8--learning english

一、积累 1.haunt Why Ghost dont haunt chinese. 为什么鬼不会出现在中国人旁边? 2.confess i have a confession to make ... I actally a blind. 我要坦白一件事……我其实是个盲人。 3.brake Press S button to brake, or to reverse if the vehicle has stopped, 按住…

android.os.NetworkOnMainThreadException

问题 android.os.NetworkOnMainThreadException详细问题 核心代码如下: import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ja…