JTree: how to check if current node is a file

老子叫甜甜 提交于 2020-02-05 02:35:05

问题


I am using the following code to populate a JTree which is working perfectly

File [] children = new File(directory).listFiles(); // list all the files in the directory
for (int i = 0; i < children.length; i++) { // loop through each
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(children[i].getName());
    // only display the node if it isn't a folder, and if this is a recursive call
    if (children[i].isDirectory() && recursive) {
        parent.add(node); // add as a child node
        listAllFiles(children[i].getPath(), node, recursive); // call again for the subdirectory
    } else if (!children[i].isDirectory()){ // otherwise, if it isn't a directory
        parent.add(node); // add it as a node and do nothing else
    }
}

Give a directory string, it adds all the files in that directory to the JTree, my problem is that i am unable to get the file from each of the nodes... i know you can use

jtree.getLastSelectedPathComponent()

to get the last selected component but what i really what is to check if the selected component is of type File and if it is, return the path of that file... does anyone know how to do this?


回答1:


The DefaultMutableTreeNode you are using contains a 'userObject', which in your case is the String representing the name:

DefaultMutableTreeNode node = new DefaultMutableTreeNode(children[i].getName());

If you would store the File in the node (or any unique identifier for a File) you can retrieve it using the available getter.

If you opt for this approach, you will probably have to change the renderer on the tree. A renderer with equivalent behavior can be implemented by extending the DefaultTreeCellRenderer and overriding the getTreeCellRendererComponent as follows

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus){
  Component result = super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus );
  if ( value instanceof DefaultMutableTreeNode && ((DefaultMutableTreeNode)value).getUserObject() instanceof File ){
     ((JLabel)result).setText( (File)((DefaultMutableTreeNode)value).getUserObject()).getName() );
  }
}

Note: the code above is not tested. I hope I did not made any mistakes in my brackets, ... (too lazy to fire up my IDE)




回答2:


Here is a small snippet looking more or less like yours (it would have been easier if you could have provided an SSCCE). Basically, I changed the user object associated with the DefaultMutableTreeNode from a String to a File. I also added a customized TreeCellRenderer to only display the name of the File (and not its absolute path), and a TreeSelectionListener that outputs to the console the current selected File object.

import java.awt.Component;
import java.io.File;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

public class TestTreeFile {

    protected void initUI() {
        JFrame frame = new JFrame(TestTreeFile.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTree tree = new JTree(createTreeModel(new File(System.getProperty("user.dir")), true));
        tree.setCellRenderer(new DefaultTreeCellRenderer() {
            @Override
            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) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                    if (node.getUserObject() instanceof File) {
                        setText(((File) node.getUserObject()).getName());
                    }
                }
                return this;
            }
        });
        tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {

            @Override
            public void valueChanged(TreeSelectionEvent e) {
                Object object = tree.getLastSelectedPathComponent();
                if (object instanceof DefaultMutableTreeNode) {
                    Object userObject = ((DefaultMutableTreeNode) object).getUserObject();
                    if (userObject instanceof File) {
                        File file = (File) userObject;
                        System.err.println("Selected file" + file.getAbsolutePath() + " Is directory? " + file.isDirectory());
                    }
                }
            }
        });
        JScrollPane pane = new JScrollPane(tree);
        frame.add(pane);
        frame.setSize(400, 600);
        frame.setVisible(true);
    }

    private DefaultMutableTreeNode createTreeModel(File file, boolean recursive) {
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(file);
        if (file.isDirectory() && recursive) {
            File[] children = file.listFiles(); // list all the files in the directory
            if (children != null) {
                for (File f : children) { // loop through each
                    node.add(createTreeModel(f, recursive));
                }
            }
        }
        return node;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestTreeFile().initUI();
            }
        });
    }
}

You may also want to take a look at this File Browser GUI.




回答3:


I'm using something like this:

private boolean isFileSelected()
{
    TreePath treePath = tree.getSelectionPath();
    Object lastPathComponent = treePath.getLastPathComponent();
    DefaultMutableTreeNode node = (DefaultMutableTreeNode) lastPathComponent;

    return node.getUserObject() instanceof MyNodeObject;
}

MyNodeObject should be different from the folder data types so you can identify if the node is a file or not.



来源:https://stackoverflow.com/questions/11419004/jtree-how-to-check-if-current-node-is-a-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!