Directory tree in Java
Using JTree and the javax.swing.tree package
The package javax.swing.tree holds some interesting classes for working
with any kind of tree structures, which we have looked at
previously. Combined with the JTree class,
it makes a good framework for displaying tree structures in the GUI, like
the file system structure we'll look at in this article.
|
The most relevant classes in this case are the
javax.swing.JTree,
javax.swing.tree.TreeModel,
javax.swing.tree.MutableTreeNode,
javax.swing.tree.TreePath and
javax.swing.event.TreeSelectionListener.
The JTree will take care of the GUI side, while the TreeModel holds the data wrapped
in TreeNodes. You migth recognice this as a MVC (Model View Controller) pattern.
As for the other two classes, they are farily descriptive; TreePath expresses a path
between two hierarical nodes in the tree while the TreeSelectionListener listens
for node selection.
|
|
A typical usage of the javax.swing.tree classes was seen in the
week 43 2002 excercise. Typically, you create a root
node, optionally add sub nodes, create a model with a reference to the root node and
add the model to the JTree.
TreeNode root = new DefaultMutableTreeNode("Root");
TreeModel treeModel = new DefaultTreeModel(root);
JTree tree = new JTree( treeModel );
In this example the root note will be one called Computer, or My Computer as the friendly
term goes. If we are dealing with a Unix or Linux OS, this might be unnecessary, since
there is only one root file system, however on Windows there are usually several drives
with a seprate root name. In this article we handle this by creating the abstract Computer
root node and add any concret root files systems as children to this.
MutableTreeNode root =
new DefaultMutableTreeNode("Computer");
//get all nodes for top file systems or disks
File roots[] = File.listRoots();
int i = 0;
for(File f : roots) {
String name = f.getAbsoluteFile().toString());
DefaultMutableTreeNode node =
new DefaultMutableTreeNode(name);
root.insert(node, i++);
}
|
|
The second task is to capture the selection event and expand the node with subdirectories
if they exisit. In this example we have an inner class which implements TreeSelectionListener
and gets a TreeSelectionEvent, which contains the selected node and the tree path to it. This
can be retrived as shown below.
TreePath path = e.getNewLeadSelectionPath();
DefaultMutableTreeNode curNode =
(DefaultMutableTreeNode)path.getLastPathComponent();
From the TreePath we can construct the file system path by looking at the data object in each
node and concat them with the correct file separator
Object nodes[] = path.getPath();
String dir = "";
for (int i = 1; i < nodes.length; i++) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) nodes[i];
dir += (String)node.getUserObject();
dir += File.separator;
}
Note how the for-loop starts at 1, since the node element at index 0 is the Computer node which
we are not interested in for the file path.
|
|
Finally, we need a mechanism for getting all sub-directories, if any, of the selected
node and add them as sub-nodes. The first task can be accived very easily by
implementing the java.io.FileFilter and using it
in the File.listFiles() method. In the code below the path variable holds
the complete file path of the node to expand.
DirectoryFileFilter filter =
new DirectoryFileFilter();
File dir = new File(path);
File subDirs[] = dir.listFiles(filter);
The DirectoryFileFilter only has to implement one simple method:
public boolean accept(File f) {
return f.isDirectory();
}
|
|
The complete example can be downloaded below. Note that this code will
be part of an open source application, and is licenced under
LGPL.
FileTreePanel.java
DirectoryFileFilter.java
|
|
|