问题
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