博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JTree实现文件树
阅读量:4968 次
发布时间:2019-06-12

本文共 4228 字,大约阅读时间需要 14 分钟。

这篇文章介绍的内容其实跟TWaver的组件没有任何关系,但是个人觉得还是挺有意思的,所以发出来共享一下。这个文件树(如下图)完全基于swing的JTree组件实现,先看一下最后我们完成的效果:

运行截图:


功能介绍:


  • 树状呈现文件系统结构
  • 文件的图标应该使用系统图标
  • 鼠标滑过时改变当前节点的背景色(如图中"Windows"节点的砖红色背景)

先看一下类结构:

  • FileTreeTest 程序入口
  • FileTree 文件树,从JTree继承
  • FileNode 封装的文件节点,包括文件名,文件图标和实际的File类及其它标识
  • FileTreeRenderer 定制的节点渲染器,从DefaultTreeCellRenderer继承
  • FileTreeModel 定制的TreeModel,从DefaultTreeModel继承

考虑到系统文件会很多,在程序开始就初始化整个树是不现实的,所以我采取一种延迟加载的策略,只有当要展开某个节点的时候,才去初始化它的子节点,在FileTree的构造里加一个监听:

addTreeWillExpandListener(new TreeWillExpandListener() {            @Override            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {                DefaultMutableTreeNode lastTreeNode =(DefaultMutableTreeNode) event.getPath().getLastPathComponent();                FileNode fileNode = (FileNode) lastTreeNode.getUserObject();                if (!fileNode.isInit) {                    File[] files;                    if (fileNode.isDummyRoot) {                        files = fileSystemView.getRoots();                    } else {                        files = fileSystemView.getFiles(                                ((FileNode) lastTreeNode.getUserObject()).file,                                false);                    }                    for (int i = 0; i < files.length; i++) {                       //文件名和图标都是通过fileSystemView得到                        FileNode childFileNode = new FileNode(                                fileSystemView.getSystemDisplayName(files[i]),                                fileSystemView.getSystemIcon(files[i]), files[i],                                false);                        DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(childFileNode);                        lastTreeNode.add(childTreeNode);                    }                    //通知模型节点发生变化                    DefaultTreeModel treeModel1 = (DefaultTreeModel) getModel();                    treeModel1.nodeStructureChanged(lastTreeNode);                }                //更改标识,避免重复加载                fileNode.isInit = true;            }            @Override            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {            }        });

当然这种方式需要TableModel的配合,我重载了DefaultTreeModel,在构造里初始化根节点,然后重载isLeaf方法,具体代码可以下载附件查看。

接下来思考一下鼠标滑过改变背景色怎么实现。

写这段代码的时候,我想起来了我刚学Renderer的时候的一个错误的认识:误以为每个节点都有一个Renderer并且妄图在Renderer上加监听!在此强调一下:Renderer只是一个渲染器,要显示节点的时候,JTree就调用它渲染并画到屏幕上,但是无论有多少节点,一个JTree只有一个Renderer!

Renderer上加监听行不通,我们就转换一下思路,在JTree上加鼠标move监听,然后repaint鼠标所在的节点。

addMouseMotionListener(new MouseAdapter() {            @Override            public void mouseMoved(MouseEvent e) {//获得鼠标所在的TreePath                TreePath path=getPathForLocation(e.getX(), e.getY());//计算repaint的区域并repaint JTree                if(path!=null){                    if(mouseInPath!=null){                        Rectangle oldRect=getPathBounds(mouseInPath);                        mouseInPath=path;                        repaint(getPathBounds(path).union(oldRect));                    }else{                        mouseInPath=path;                        Rectangle bounds=getPathBounds(mouseInPath);                        repaint(bounds);                    }                }else if(mouseInPath!=null){                    Rectangle oldRect=getPathBounds(mouseInPath);                    mouseInPath=null;                    repaint(oldRect);                }            }        });

需要在JTree中保存鼠标滑过的TreePath(mouseInPath),这样在Renderer中才可以改变mouseInPath的背景色

FileTree fileTree=(FileTree)tree;        JLabel label= (JLabel) super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus);        DefaultMutableTreeNode node=(DefaultMutableTreeNode)value;        FileNode fileNode=(FileNode)node.getUserObject();        label.setText(fileNode.name);        label.setIcon(fileNode.icon);        label.setOpaque(false);//如果当前渲染的节点就是鼠标滑过的节点,改变背景色        if(fileTree.mouseInPath!=null&&                fileTree.mouseInPath.getLastPathComponent().equals(value)){            label.setOpaque(true);            label.setBackground(new Color(255,0,0,90));        }        return label;

至此这个文件树就写完了!全部代码在附件,有兴趣的同学可以下载看看,也希望看过的同学有好的想法来交流一下。 附件:

转载于:https://www.cnblogs.com/twaver/archive/2012/11/05/2754855.html

你可能感兴趣的文章
简单权限管理系统原理浅析
查看>>
springIOC第一个课堂案例的实现
查看>>
求输入成绩的平均分
查看>>
php PDO (转载)
查看>>
wordpress自动截取文章摘要代码
查看>>
[置顶] 一名优秀的程序设计师是如何管理知识的?
查看>>
scanf和gets
查看>>
highcharts 图表实例
查看>>
ubuntu下如何查看用户登录及系统授权相关信息
查看>>
秋季学期学习总结
查看>>
SpringBoot 优化内嵌的Tomcat
查看>>
【LaTeX】E喵的LaTeX新手入门教程(1)准备篇
查看>>
highcharts曲线图
查看>>
extjs动态改变样式
查看>>
PL/SQL Developer 查询的数据有乱码或者where 字段名=字段值 查不出来数据
查看>>
宏定义
查看>>
笔记:git基本操作
查看>>
生成php所需要的APNS Service pem证书的步骤
查看>>
JavaWeb之JSON
查看>>
HOT SUMMER 每天都是不一样,积极的去感受生活 C#关闭IE相应的窗口 .
查看>>