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