使用swing的JTree加载本地资源目录,当本地文件和文件夹比较多时加载速度会很慢,故使用懒加载的方式以提高加载速度。
先只加载一层目录和文件,当点击展开目录时再加载它的子节点。
实现代码如下:
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
/**
* 懒加载本地资源目录
* @author dqk
*
* @date 2022年11月4日
*/
public class LoadLazyTree {
public static void main(String[] args) {
openWindow();
}
private static void openWindow() {
JFrame jFrame = new JFrame();
File[] listRoots = File.listRoots();
// 递归构建文件树的根节点
DefaultMutableTreeNode rootNode = buildrootNode(listRoots);
DefaultTreeModel defaultTreeModel = new DefaultTreeModel(rootNode);
//将加载的节点设置成“询问是否有子节点”,DefaultMutableTreeNode.setAllowsChildren(false);时节点为叶节点,也就是没有子节点
defaultTreeModel.setAsksAllowsChildren(true);
// 使用根节点去初始化一颗树
JTree fileBrowserTree = new JTree(defaultTreeModel);
JScrollPane jScrollPane = new JScrollPane(fileBrowserTree);
//树节点将要展开或者关闭时
fileBrowserTree.addTreeWillExpandListener(new TreeWillExpandListener() {
//节点将要展开时触发
@Override
public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)event.getPath().getLastPathComponent();
defaultMutableTreeNode.removeAllChildren();
Object objtreeNodeEntrty = defaultMutableTreeNode.getUserObject();
if(TreeNodeEntity.class.isInstance(objtreeNodeEntrty)) {
TreeNodeEntity treeNodeEntrty = (TreeNodeEntity)objtreeNodeEntrty;
String path = treeNodeEntrty.getPath();
buildChildNode(new File(path),defaultMutableTreeNode);
//当本地目录中文件或者文件夹有改变时,树节点重新加载后需调用此方法刷新树节点,否则树节点还是显示的未改变之前的
//jTree.updateUI();直接调用会出现空指针问题
//解决办法:不能直接调用updateUI方法,需要放到SwingUtilities.invokeLater中执行;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
fileBrowserTree.updateUI();
}
});
}
}
//节点将要关闭时触发
@Override
public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
}
});
jFrame.add(jScrollPane);
jFrame.setSize(300, 600);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setLocationRelativeTo(null);
jFrame.setVisible(true);
}
/**
* 创建系统根节点
* @param rootFile
* @return
*/
public static DefaultMutableTreeNode buildrootNode(File[] rootFile) {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("系统资源");
for (File subFile : rootFile) {
TreeNodeEntity treeNodeEntity = new TreeNodeEntity();
treeNodeEntity.setName(subFile.getPath());
treeNodeEntity.setPath(subFile.getPath());
DefaultMutableTreeNode dirNode = new DefaultMutableTreeNode(treeNodeEntity);
if (!subFile.isDirectory()) {
dirNode.setAllowsChildren(false);
}
rootNode.add(dirNode);
}
return rootNode;
}
/**
* 展开节点时创建所展开节点的子节点(加载文件夹和图片类型)
* @param rootFile
* @param rootNode
*/
public static void buildChildNode(File rootFile,DefaultMutableTreeNode rootNode) {
File[] subFiles = rootFile.listFiles();
for (File subFile : subFiles) {
if(subFile!=null) {
TreeNodeEntity treeNodeEntity = new TreeNodeEntity();
treeNodeEntity.setName(subFile.getName());
treeNodeEntity.setPath( subFile.getPath());
DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(treeNodeEntity);
//只加载允许的文件类型
if (!subFile.isDirectory()) {
//将不是文件夹的节点标记为叶子节点
subNode.setAllowsChildren(false);
rootNode.add(subNode);
}else if(subFile.isDirectory()){
rootNode.add(subNode);
}
}
}
}
}
class TreeNodeEntity {
private String name;
private String path;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
// 重点在toString,节点的显示文本就是toString,否则会显示该对象的地址
public String toString(){
return name;
}
}