当前位置:编程学习 > 网站相关 >>

JTree实现文件树

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

运行截图:
 

功能介绍:
树状呈现文件系统结构
文件的图标应该使用系统图标
鼠标滑过时改变当前节点的背景色(如图中"Windows"节点的砖红色背景)
先看一下类结构:
FileTreeTest 程序入口
FileTree 文件树,从JTree继承
FileNode 封装的文件节点,包括文件名,文件图标和实际的File类及其它标识
FileTreeRenderer 定制的节点渲染器,从DefaultTreeCellRenderer继承
FileTreeModel 定制的TreeModel,从DefaultTreeModel继承
考虑到系统文件会很多,在程序开始就初始化整个树是不现实的,所以我采取一种延迟加载的策略,只有当要展开某个节点的时候,才去初始化它的子节点,在FileTree的构造里加一个监听:

 1 addTreeWillExpandListener(new TreeWillExpandListener() {
 2             @Override
 3             public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
 4                 DefaultMutableTreeNode lastTreeNode =
 5 (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
 6                 FileNode fileNode = (FileNode) lastTreeNode.getUserObject();
 7                 if (!fileNode.isInit) {
 8                     File[] files;
 9                     if (fileNode.isDummyRoot) {
10                         files = fileSystemView.getRoots();
11                     } else {
12                         files = fileSystemView.getFiles(
13                                 ((FileNode) lastTreeNode.getUserObject()).file,
14                                 false);
15                     }
16                     for (int i = 0; i < files.length; i++) {
17                        //文件名和图标都是通过fileSystemView得到
18                         FileNode childFileNode = new FileNode(
19                                 fileSystemView.getSystemDisplayName(files[i]),
20                                 fileSystemView.getSystemIcon(files[i]), files[i],
21                                 false);
22                         DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(childFileNode);
23                         lastTreeNode.add(childTreeNode);
24                     }
25                     //通知模型节点发生变化
26                     DefaultTreeModel treeModel1 = (DefaultTreeModel) getModel();
27                     treeModel1.nodeStructureChanged(lastTreeNode);
28                 }
29                 //更改标识,避免重复加载
30                 fileNode.isInit = true;
31             }
32             @Override
33             public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
34
35             }
36         });

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

接下来思考一下鼠标滑过改变背景色怎么实现。
写这段代码的时候,我想起来了我刚学Renderer的时候的一个错误的认识:误以为每个节点都有一个Renderer并且妄图在Renderer上加监听!在此强调一下:Renderer只是一个渲染器,要显示节点的时候,JTree就调用它渲染并画到屏幕上,但是无论有多少节点,一个JTree只有一个Renderer!
Renderer上加监听行不通,我们就转换一下思路,在JTree上加鼠标move监听,然后repaint鼠标所在的节点。

 1 addMouseMotionListener(new MouseAdapter() {
 2             @Override
 3             public void mouseMoved(MouseEvent e) {
 4 //获得鼠标所在的TreePath
 5                 TreePath path=getPathForLocation(e.getX(), e.getY());
 6
 7 //计算repaint的区域并repaint JTree
 8                 if(path!=null){
 9                     if(mouseInPath!=null){
10                         Rectangle oldRect=getPathBounds(mouseInPath);
11        &nbs

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,