![](/img/trans.png)
[英]java swing : display file system in jtree, and how to open the file
[英]How to insert and display new node in a JTree of the file system contents
我已經成功創建了一個小程序,該程序將在JTree中顯示文件系統內容。 它僅顯示文件夾和純文本文件。 我現在想在創建樹時將文件夾添加到樹中。 該示例程序將顯示樹並創建一個文件夾,但是不會為剛剛創建的文件夾插入新節點。 創建文件夾后如何在樹中插入節點並使樹顯示新文件夾?
非常感謝!
此類創建並顯示樹。
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
public class TreeFrame extends JFrame{
private JTree fileTree = null;
private String USER_HOME = System.getProperty("user.home");
public TreeFrame(){
super("File Tree");
setDefaultCloseOperation(EXIT_ON_CLOSE);
//Create tree
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(new File(USER_HOME));
fileTree = new JTree(new FileTreeModelTest(rootNode));
fileTree.setCellRenderer(new TreeCellRendererTest());
fileTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
//Commented out the next part because it causes a null pointer exception.
//I believe it is caused by the tree not inserting a node.
//JTree tree = (JTree)e.getSource();
//DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
//Object obj = node.getUserObject();//Causes a null pointer exception
//if(obj instanceof File){
// File f = (File)node.getUserObject();
// System.out.println(f.getAbsolutePath());
//}
}
});
JPanel panel = new JPanel();
JLabel folderLabel = new JLabel("Name:");
panel.add(folderLabel, BorderLayout.WEST);
final JTextField textField = new JTextField(25);
textField.setPreferredSize(new Dimension(100, 28));
panel.add(textField, BorderLayout.CENTER);
JButton button = new JButton("Create Foder");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//Add a folder when the menu item is clicked
DefaultMutableTreeNode node = (DefaultMutableTreeNode)fileTree.getLastSelectedPathComponent();
File f = (File)node.getUserObject();
if(f.isDirectory()){
File dir = new File(f.getAbsolutePath()+"/"+textField.getText().trim());
if(dir.mkdirs()){
System.out.println("ADDED: " + dir.getAbsolutePath());
//Insert node into tree model -- this is the part that does not seem to work.
FileTreeModelTest model = (FileTreeModelTest)fileTree.getModel();
DefaultMutableTreeNode child = new DefaultMutableTreeNode(dir);
model.insertNodeInto(child, node, node.getChildCount());
model.reload(node);
TreeNode[] nodes = model.getPathToRoot(child);
TreePath path = new TreePath(nodes);
fileTree.scrollPathToVisible(path);
fileTree.setSelectionPath(path);
}
}
}
});
panel.add(button, BorderLayout.EAST);
getContentPane().add(panel, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(fileTree);
scrollPane.setPreferredSize(new Dimension(200, 400));
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
}
public static void main(String[] args){
TreeFrame frame = new TreeFrame();
frame.setVisible(true);
}
}
此類是樹模型。
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
public class FileTreeModelTest extends DefaultTreeModel {
public FileTreeModelTest(DefaultMutableTreeNode root){
super(root);
}
private File[] getFiles(File parent){
File[] f = parent.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if(file==null)
return false;
if(file.isDirectory())
return true;
if(file.getName().toLowerCase().endsWith("txt")){
return true;
}
return false;
}
});
return f;
}
@Override
public Object getChild(Object parent, int index){
DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent;
File p = (File)node.getUserObject();
File[] pFile = getFiles(p);
DefaultMutableTreeNode child = new DefaultMutableTreeNode(pFile[index]);
return child;
}
@Override
public int getChildCount(Object parent){
DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent;
File f = (File)node.getUserObject();
if(!f.isDirectory()){
return 0;
}else{
//Is a directory, return number of folders and text files
File[] children = getFiles(f);
if(children==null) return 0;
return children.length;
}
}
@Override
public int getIndexOfChild(Object parent, Object child){
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode)parent;
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)child;
File p = (File)parentNode.getUserObject();
File c = (File)childNode.getUserObject();
File[] pFile = getFiles(p);
return Arrays.asList(pFile).indexOf(c);
}
@Override
public Object getRoot(){
return root;
}
@Override
public boolean isLeaf(Object parent){
DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent;
File f = (File)node.getUserObject();
if(f.isDirectory()){
File[] children = getFiles(f);
if(children==null) return true;
//F is a directory. If it has no files, then it is a leaf.
return children.length==0;
}else{
//F is a file. It is a leaf.
return true;
}
}
}
最后一個類是樹單元渲染器。
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
import java.io.File;
public class TreeCellRendererTest extends DefaultTreeCellRenderer {
private FileSystemView fsv = FileSystemView.getFileSystemView();
public TreeCellRendererTest(){
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if(value instanceof DefaultMutableTreeNode){
Object obj = ((DefaultMutableTreeNode) value).getUserObject();
if(obj instanceof File){
File f = (File)obj;
if(row==0){
setIcon(fsv.getSystemIcon(f));
setText(f.getPath());
}else
if(f.isFile()){
setIcon(fsv.getSystemIcon(f));
setText(f.getName());
}else{
setIcon(fsv.getSystemIcon(f));
setText(f.getName());
}
}
}
return this;
}
}
方法似乎基本不匹配。 您正在使用DefaultMutableTreeNode
,該緩存將子節點緩存在其中,但是直接通過模型管理實際節點,這在多個不同級別上造成了混亂。
如果要繼續直接監視磁盤內容(或代理它),我將創建一個自定義TreeNode
其唯一職責是監視單個目錄。
然后,我將創建一個自定義TreeModel
(可能來自DefaultTreeModel
),該模型提供了makeDirectory
方法,該方法將傳遞當前選擇的TreeNode
和目錄名稱。
然后,此方法將負責目錄的物理創建以及JTree
的結構更改通知(通過nodesWereInserted
方法)。 我可能會讓這個節點返回一個代表子節點的TreeNode
實例。
這種方法存在很多問題,尤其是在引用對象方面。 在當前方法中,每當調用getChild
時,您都將創建一個新的DefaultMutableTreeNode
,如果API的某些部分依賴那些對給定位置/數據保持不變的引用,則可能會導致問題,這將需要您維護某種內部緩存,將File
與TreeNode
鏈接...這有損於目標...
更好的方法可能是利用現有的“可變樹節點” API,每個節點仍將負責單個File
,但也將緩存結果。 這里的問題是管理何時應填充節點(因為您不想填充未擴展的目錄節點)。
我打算使用“監視服務” API,然后使用“可變樹節點” API並在其中緩存子文件(根據需要),這將只是問題...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.