随笔-50  评论-55  文章-8  trackbacks-0

一般情况下,构建一个 SWING 树,都是先要构建好存放数据的模型 (TreeModel), 在一般情况下,实现起来都没有问题,但当数据量非常大的时候,一次性构建好 TreeModel ,将会花费很多时间,界面处于灰掉的状态(当然可以另开其他线程,可以操作其他界面),这个给用户的感觉非常差。解决这个问题的关键在于,树模型的数据。我们都知道,系统文件是一层一层很有层次性,这样我们就可以以一个文件(不管是文件还是文件夹)为树节点,当初次加载树的时候,点击树节点,先判断其有没有子节点,若无,就去读去该节点的保存的文件信息,若为文件夹,就去取其文件夹下的所有文件,构造出树节点,加到树中。第二次点击的时候,就不会去读磁盘文件系统了。

代码清单:

import javax.swing.tree.DefaultMutableTreeNode;

import javax.swing.tree.DefaultTreeModel;

import java.io.*;

import java.awt.*;

import javax.swing.*;

import javax.swing.tree.TreeCellRenderer;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import javax.swing.tree.TreePath;

/**

 * <p>Title: JDHSystemFileTree</p>

 * <p>Description: 系统目录树,动态生成,解决载入慢的问题 </p>

 * <p>Copyright: Copyright (c) 2007</p>

* @author 蒋家狂潮

 * @version 1.0

 */

public class SystemFileTree {

    private DefaultTreeModel model;

    private JTree tree;

    public SystemFileTree () {

        JFrame f=new JFrame();

        f.getContentPane().setLayout(new BorderLayout());

        tree=new JTree();

        tree.addMouseListener(new MouseAdapter(){

            public void mousePressed(MouseEvent e){

                node_mouseAction(e);

            }

        });

        JScrollPane scroll=new JScrollPane(tree);

        f.getContentPane().add(scroll,BorderLayout.CENTER);

 

        f.setLocation(250,250);

        f.setSize(new Dimension(300,500));

        f.setVisible(true);

    }

    private void node_mouseAction(MouseEvent e){

        int row = tree.getRowForLocation(e.getX(), e.getY());

        PathNode pathNode =null;

        if(row != -1){

        TreePath path = tree.getPathForRow(row);

        pathNode = (PathNode)path.getLastPathComponent();

 

        if(pathNode.isFolder()&&pathNode.getChildCount()==0){

            builderNode(pathNode);

            tree.expandPath(path);

        }

        }

 

    }

    private PathNode builderNode(PathNode pathNode){

        String filePath= pathNode.getValue().toString();

        File file=new File(filePath);

        File[] files=file.listFiles();

       for(int i=0;i<files.length;i++){

           PathNode node=new PathNode(files[i].getName(), files[i].getAbsolutePath(),files[i].isDirectory());

           pathNode.add(node);

       }

        return pathNode;

    }

    private void initData(String  rootPath){

 

        File f=new File(rootPath);

 

        PathNode root=new PathNode(f.getName(), rootPath,f.isDirectory());

 

        File[] files=f.listFiles();

        for(int i=0;i<files.length;i++){

            PathNode node=new PathNode(files[i].getName(), files[i].getAbsolutePath(),files[i].isDirectory());

            root.add(node);

        }

 

 

        model=new DefaultTreeModel(root);

        tree.setModel(model);

        FileTreeRenderer renderer=new FileTreeRenderer();

        tree.setCellRenderer(renderer);

        tree.repaint();

}

 

    class FileTreeRenderer implements TreeCellRenderer{

        private Icon folder_open=new ImageIcon("icons/folder_open.jpg");

        private Icon folder_close=new ImageIcon("icons/folder_close.jpg");

        private Icon file=new ImageIcon("icons/file.gif");

        public Component getTreeCellRendererComponent(JTree tree, Object value,

                boolean selected, boolean expanded, boolean leaf, int row,

                boolean hasFocus) {

            JLabel label = null;

            if (value != null) {

                System.out.println(value.getClass().toString());

                if(value instanceof PathNode){

 

                    PathNode pathNode = (PathNode) value;

                    if (pathNode.isFolder()) {

                        if (expanded) {

                            label = new JLabel(pathNode.getUserObject().

                                               toString(),

                                               folder_open, JLabel.RIGHT);

                        } else if(!expanded||leaf) {

                            label = new JLabel(pathNode.getUserObject().

                                               toString(),

                                               folder_close, JLabel.RIGHT);

                        }

                    } else {

                        label = new JLabel(pathNode.getUserObject().toString(),

                                           file, JLabel.RIGHT);

                    }

                    return label;

                }

            }

            return label;

        }

}

 

    class PathNode extends DefaultMutableTreeNode{

        Object value;

        boolean isFolder;

       public PathNode(String name,Object value,boolean isFolder){

           super(name);

           this.value=value;

           this.isFolder=isFolder;

        }

        public Object getValue(){

          return value;

        }

        public boolean isFolder(){

            return isFolder;

        }

    }

    public static void main(String args[]){

        JDHSystemFileTree tree=new JDHSystemFileTree();

         // 给个路径作演示

        tree.initData("D:/");

    }

}

 

当然可以进一步实现界面的易用性,就是在初始点击之后,加载完之前,让鼠标变成等待的形状。
                       

posted on 2007-10-30 16:22 蒋家狂潮 阅读(1519) 评论(1)  编辑  收藏 所属分类: Swing

评论:
# re: SWING展示系统文件树 2008-07-24 08:43 | grid
上面的源代码的最后的MAIN函数错了,正确应该如下:
public static void main(String args[]) {
//JDHSystemFileTree tree = new JDHSystemFileTree();
SystemFileTree tree = new SystemFileTree();
// 给个路径作演示
tree.initData("D:/");
}  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: