一般情況下,構建一個 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:/");
??? }
}
當然可以進一步實現界面的易用性,就是在初始點擊之后,加載完之前,讓鼠標變成等待的形狀。