import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
public class TreeDemo extends JFrame {
private static final long serialVersionUID = 1L;
private DefaultTreeModel createTreeModel() { // 创建根结点, 只执行一次
File root = new File("E:/");
FileNode rootNode = new FileNode(root);
rootNode.explore(); // 第一层结构显示
return new DefaultTreeModel(rootNode);
}
public TreeDemo() {
final JTree tree = new JTree(createTreeModel()); // 返回的是根结点
// DefaultTreeModel
JScrollPane l_scrollPane = new JScrollPane(tree);
getContentPane().add(l_scrollPane, BorderLayout.WEST);
final JTextArea textArea = new JTextArea(10, 10);
JScrollPane r_scrollPane = new JScrollPane(textArea);
getContentPane().add(r_scrollPane, BorderLayout.CENTER);
// getContentPane().add(GJApp.getStatusArea(), BorderLayout.SOUTH);
tree.addTreeExpansionListener(new TreeExpansionListener() { // 重写JTree的事件监听器
public void treeCollapsed(TreeExpansionEvent e) {
}
public void treeExpanded(TreeExpansionEvent e) {
TreePath path = e.getPath(); // 表示到某节点的一条路径 返回已被扩张 /
// 折叠的值的路径
FileNode node = (FileNode) path.getLastPathComponent(); // 文件路径
// <-
// (树)路径的最后一个组件
if (!node.isExplored()) { // public boolean
// isExplored() { return
// explored; }
// 该节点从未打开时为false
DefaultTreeModel model = (DefaultTreeModel) tree
.getModel(); // 返回提供数据的 TreeModel
GJApp.updateStatus("exploring ...");
UpdateStatus us = new UpdateStatus();
us.start();
node.explore();
model.nodeStructureChanged(node); // 当彻底改变节点的子节点和子节点的子节点...
// 时调用该方法,这将导致记入一个
// treeStructureChanged
// 事件
}
}
class UpdateStatus extends Thread {
public void run() {
try {
Thread.sleep(450);
} catch (InterruptedException e) {
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GJApp.updateStatus(" ");
}
});
}
}
});
}
public static void main(String args[]) {
GJApp.launch(new TreeDemo(), "JTree File Explorer", 300, 300, 450,
400);
}
}
class FileNode extends DefaultMutableTreeNode {
private static final long serialVersionUID = 1L;
private boolean explored = false;
public FileNode(File file) {
setUserObject(file);
}
public String toString() {
File file = (File) getUserObject();
String filename = file.toString();
int index = filename.lastIndexOf(File.separator);
return (index != -1 && index != filename.length() - 1) ? filename
.substring(index + 1) : filename;
}
public boolean getAllowsChildren() {
return isDirectory();
}
public boolean isLeaf() {
return !isDirectory();
}
public File getFile() {
return (File) getUserObject();
} // 文件
public boolean isExplored() {
return explored;
}
public boolean isDirectory() {
File file = getFile(); // 文件名
return file.isDirectory(); // 测试当前 File 对象表示的文件是否是一个路径, 还能展开
}
public void explore() { // 递归实现
if (!isDirectory()) // 当前文件路径所对应是系统文件是文件夹吗?
return;
if (!isExplored()) { // 该层第一次被打开, 展开当前结点的所有子元素
File file = getFile(); // 该节点的用户对象
File[] children = file.listFiles();
for (int i = 0; i < children.length; ++i)
add(new FileNode(children[i])); // 子元素被实例化, 并添加到当前节点下
// 系统是如何分辨子元素是文件夹还是文件, 因为涉及到两种图标
explored = true;
System.out.println("文件夹被第一次打开, 添加新节点时执行");
}
}
}
class GJApp extends WindowAdapter {
static private JPanel statusArea = new JPanel();
static private JLabel status = new JLabel(" ");
public static void launch(final JFrame f, String title, final int x,
final int y, final int w, int h) {
f.setTitle(title);
f.setBounds(x, y, w, h);
f.setVisible(true);
statusArea.setBorder(BorderFactory.createEtchedBorder());
statusArea.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
statusArea.add(status);
status.setHorizontalAlignment(JLabel.LEFT);
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.exit(0);
}
});
}
static public JPanel getStatusArea() {
return statusArea;
}
static public void updateStatus(String s) {
status.setText(s);
}
}