簡體   English   中英

如何在文件系統內容的JTree中插入和顯示新節點

[英]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的某些部分依賴那些對給定位置/數據保持不變的引用,則可能會導致問題,這將需要您維護某種內部緩存,將FileTreeNode鏈接...這有損於目標...

更好的方法可能是利用現有的“可變樹節點” API,每個節點仍將負責單個File ,但也將緩存結果。 這里的問題是管理何時應填充節點(因為您不想填充未擴展的目錄節點)。

我打算使用“監視服務” API,然后使用“可變樹節點” API並在其中緩存子文件(根據需要),這將只是問題...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM