Before we start, I'd like to note that I'm rather new to JTree and its relatives.
The children in my nodes show the relative path back to its parent, but I'd like for it not to.
Here is a picture of what it looks like
http://puu.sh/azCJa/8dd84029b7.png
I'd like for it to be like:
testing 0
>testing 1
>>file 1
not
testing 0
>testing 0\testing 1
>>...
Here is some runnable code.
import java.awt.Color;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
public class NGui {
JFrame frame;
private JTree tree;
public NGui() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setResizable(false);
frame.setBounds(100, 100, 493, 608);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 212, 500);
frame.getContentPane().add(scrollPane);
tree = new JTree(addNodes(null, new File(getWorkPath())));
tree.setRootVisible(false);
tree.setShowsRootHandles(true);
tree.setBorder(new LineBorder(new Color(0, 0, 0)));
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
scrollPane.setViewportView(tree);
tree.getSelectionModel().addTreeSelectionListener(
new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
treeValueChanged(e);
}
});
}
private String getWorkPath() {
return System.getProperty("user.home") + "\\Program Name\\";
}
private void treeValueChanged(TreeSelectionEvent e) {
}
DefaultMutableTreeNode addNodes(DefaultMutableTreeNode top, File dir) {
String curPath = dir.getPath();
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
curPath.replace(getWorkPath(), ""));
if (top != null) { // should only be null at root
log("Adding curPath: " + root);
top.add(root);
}
Vector<String> ol = new Vector<String>();
String[] tmp = dir.list();
for (String s : tmp) {
log("Adding file: " + s);
ol.addElement(s);
}
Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
File file;
Vector<String> files = new Vector<String>();
// for dirs
for (int i = 0; i < ol.size(); i++) {
String filePath = ol.elementAt(i);
String newPath;
if (curPath.equals(".")) // if root
newPath = filePath;
else
// not root
newPath = curPath + File.separator + filePath;
file = new File(newPath);
log(String.format("cur: %s | file: %s | new: %s", curPath,
filePath, newPath));
// if not a file then go inside folder and get files
if (file.isDirectory())
addNodes(root, file);
else if (filePath.contains(".txt")) // txt files only
files.addElement(filePath);
}
// for files
for (int fnum = 0; fnum < files.size(); fnum++)
root.add(new DefaultMutableTreeNode(files.elementAt(fnum).replace(getWorkPath(), ""), true));
return root;
}
public void log(Object o) {
System.out.println(o);
}
}
The cause of your issue is here...
if (curPath.equals(".")) // if root
newPath = filePath;
else
// not root
newPath = curPath + File.separator + filePath;
Basically, what it's saying is, unless you are the root node, prefix curPath
(which is dir.getPath()
) to the filePath
...which is why you get path/path
in your tree...
The entire if
statement is pointless, based on what you want to achieve and be complete replace with...
newPath = filePath;
In face, you could get rid of newPath
and simple use filePath
directly...
Updated
Your core design is simply not capable of doing what it seems you are trying to achieve...
Trying to maintain path information as String
s is overly complicated and error prone, it is much simpler to maintain the File
reference, which provides you with all the information you need to render the file name and access the file for other purposes...the right tool for the job...
Some background, the default TreeCellRenderer
used by JTree
simply uses the toString
method of the object in the TreeModel
to renderer something to the UI. In the case of DefaultMutableTreeNode
, this simply uses the toString
method of the userData
object you pass it, so this means, when you do curPath.replace(getWorkPath(), "")
, this is what eventually gets to the screen, but isn't what you want.
Instead, you should be passing the actual File
to the DefaultMutableTreeNode
and using a custom TreeCellRenderer
to modify the value going to the screen, for example...
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
public class NGui {
JFrame frame;
private JTree tree;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
new NGui();
}
});
}
public NGui() {
initialize();
}
private void initialize() {
frame = new JFrame();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 212, 500);
frame.getContentPane().add(scrollPane);
tree = new JTree(addNodes(new File(getWorkPath())));
tree.setRootVisible(false);
tree.setShowsRootHandles(true);
tree.setBorder(new LineBorder(new Color(0, 0, 0)));
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
scrollPane.setViewportView(tree);
tree.getSelectionModel().addTreeSelectionListener(
new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
treeValueChanged(e);
}
});
tree.setCellRenderer(new FileTreeCellRenderer());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private String getWorkPath() {
// return System.getProperty("user.home") + "\\Program Name\\";
return ".";
}
private void treeValueChanged(TreeSelectionEvent e) {
}
public DefaultMutableTreeNode addNodes(File dir) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir);
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
node.add(addNodes(file));
} else {
node.add(new DefaultMutableTreeNode(file));
}
}
return node;
}
public class FileTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (value instanceof DefaultMutableTreeNode) {
value = ((DefaultMutableTreeNode)value).getUserObject();
if (value instanceof File) {
value = ((File) value).getName();
}
}
return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
}
}
}
Take a look at Customizing a Tree's Display for more details