Geertjan's Blog

  • October 6, 2007

TreeTableView in J2SE Application

Geertjan Wielenga
Product Manager
One thing (in fact, the first thing) the developers we visited in Budapest asked us for was "a tutorial on TreeTableView". Not surprising, is it. Using the approach described yesterday, (i.e., create a J2SE application instead of a NetBeans module), I adapted Jarda's file browser, so that you can see the full path as well as whether the folder is hidden or not, in a sortable TreeTableView:

I've found thus far that it is much easier to learn explorer views via J2SE projects than to do so via NetBeans modules. (More than likely this is also true for most other NetBeans APIs.) Firstly, because compilation and deployment is much faster. (I imagine that debugging will be a piece of cake too.) Secondly, because you're able to focus on a very specific API, instead of needing to first create a scenario in which the API makes sense. Also, this approach forces you to think very explicitly about which APIs you need, because you can't rely on the search functionality in the NetBeans module project's Project Properties dialog box. (Although, you could use another module project for this purpose, but you still need to explicitly add the required JAR to your J2SE project, which entails a more explicit thought process than simply working though a dialog.) As a result, you're more aware of the location of the classes you need. That can't be a bad thing, can it? So, here's my entire source structure:

Note: I used the Library Manager to create a library called 'ExplorerViews'. Then I added the five JARs you see above, from the NetBeans IDE distribution. Then I attached that library to my project's Libraries node.

And here is all my code:

package demo;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.openide.nodes.Sheet;
public final class FileNode extends AbstractNode {
static String PROP_FULL_PATH = "space";
static String IS_HIDDEN = "is hidden";
private File file;
private FileNode(File f) {
super(new FileKids(f));
file = f;
public static Node files() {
AbstractNode n = new AbstractNode(new FileKids(null));
return n;
public static class FileKids extends Children.Keys<File> {
File file;
public FileKids(File file) {
this.file = file;
protected void addNotify() {
if (file == null) {
File[] arr = File.listRoots();
if (arr.length == 1) {
arr = arr[0].listFiles();
} else {
File[] arr = file.listFiles();
if (arr != null) {
public Node[] createNodes(File f) {
FileNode n = new FileNode(f);
return new Node[]{n};
public Node[] getNodes(boolean arg0) {
return super.getNodes(arg0);
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
ss.put(new FullPathProperty(file));
ss.put(new IsHiddenProperty(file));
return s;
private class FullPathProperty extends PropertySupport.ReadOnly<String> {
File file;
public FullPathProperty(File file) {
super(FileNode.PROP_FULL_PATH, String.class, "Full path", "Complete path is shown");
this.file = file;
public String getValue() throws IllegalAccessException, InvocationTargetException {
return file.getAbsolutePath();
private class IsHiddenProperty extends PropertySupport.ReadOnly<String> {
File file;
public IsHiddenProperty(File file) {
super(FileNode.IS_HIDDEN, String.class, "Is hidden", "Is hidden status is shown");
this.file = file;
public String getValue() throws IllegalAccessException, InvocationTargetException {
return file.isHidden();

By the way, before showing the TreeTableView code, it is worth pointing out that, as described yesterday, I can drag and drop the TreeTableView from the Palette, after adding the org.openide.explorer.ExplorerManager JAR to it. By doing so, I was also able to set some properties on the TreeTableView via the IDE's Properties sheet, instead of doing so via code. That was a pretty handy approach to working with TreeTableView.

package demo;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.NodeTableModel;
import org.openide.nodes.Node;
public class TreeTableView extends javax.swing.JFrame implements ExplorerManager.Provider {
private ExplorerManager manager;
private NodeTableModel nodeTableModel;
private FileNode f;
private Node.Property[] props;
/\*\* Creates new form NewJFrame \*/
public TreeTableView() {
manager = new ExplorerManager();
nodeTableModel = new NodeTableModel();
nodeTableModel.setNodes(new Node[]{FileNode.files()});
Node[] nodes = FileNode.files().getChildren().getNodes();
props = nodes[0].getPropertySets()[0].getProperties();
props[0].setValue("ComparableColumnTTV", Boolean.TRUE); //NOI18N
props[0].setValue("SortingColumnTTV", Boolean.TRUE);
//Second property column is sortable, but not initially sorted,
//so initially will have no arrow icon:
props[1].setValue("ComparableColumnTTV", Boolean.TRUE); //NOI18N
/\*\* This method is called from within the constructor to
\* initialize the form.
\* WARNING: Do NOT modify this code. The content of this method is
\* always regenerated by the Form Editor.
private void initComponents() {
treeTableView1 = new org.openide.explorer.view.TreeTableView(nodeTableModel);
treeTableView1.setBorder(javax.swing.BorderFactory.createTitledBorder("File System Browser"));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
.addComponent(treeTableView1, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(treeTableView1, javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE)

\* @param args the command line arguments
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TreeTableView().setVisible(true);
// Variables declaration - do not modify
private org.openide.explorer.view.TreeTableView treeTableView1;
// End of variables declaration
public ExplorerManager getExplorerManager() {
return manager;

Finally, if you want to learn about the properties that relate to TreeTableView, see the following:

Also, I found, after googling, that I have quite a lot of relatively useful information in this blog on this subject already. I learned quite a lot from searching in my blog and found myself being surprised at my own insights.

Join the discussion

Comments ( 8 )
  • Emilian Bold Saturday, October 6, 2007

    Too bad not all Platform APIs are so JAR-friendly as to be usable in a standard j2se project.

    Trust me, once you need to use some API that loves for no particular reason the layer filesystem for example, you're in a world of unneeded workarounds.

    Heh, I liked the stuff about searching your own blog. I also use it as a part-time note-taking app because I know I'll need it later. So I just put it there and when I run into an issue again I'll just know it's on the blog (this probably decreases the quality of the blog posts, but oh well...)

  • guest Sunday, October 7, 2007

    I had to change :


    public Node[] createNodes(File f)



    public Node[] createNodes(Object f)

    Note: I don't build with netbeans but with my own build.xml. (I tried the jars from netbeans 5.5 and netbeans 6.0 with the same result)


  • Sven Reimers Sunday, October 7, 2007

    You need to change

    public static class FileKids extends Children.Keys {


    public static class FileKids extends Children.Keys<File> {

    for NetBeans6 to get @Override working.

  • Sven Reimers Sunday, October 7, 2007

    Did you ever tried to change this into a table view and hide the TreeTableColumn?

  • Geertjan Sunday, October 7, 2007

    Sorry, Kees, I didn't add the HTML tags as indicated by Sven above, so you couldn't see the &lt;File&gt; part in the signature. I've fixed it in the code listing above. That will fix your problem. Sven interesting idea, haven't tried it, but will look at it.

  • Kees Kuip Sunday, October 7, 2007

    I want to try to replace the swingx treetable for the one in netbeans for my open source project 'jmeld'.

    Is it possible to change the background color of a row? Swingx has RowHighLighters. I want to even and uneven rows to have a different color.

    Is it possible to change the disabled text color? The color now is lightgray (on my system) and is hardly readable.

  • Geertjan Sunday, October 7, 2007

    Kees, see the next blog entry for some pointers to help you.

  • John Tuesday, August 31, 2010

    Geertjan - Really love and appreciate your tutorials. However I think it would be great if you added something to the top of this pointing to OutlineView as a better, newer alternative to TTV.

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.