Geertjan is a DZone Zone Leader and has posted 453 posts at DZone. You can read more from them at their website. View Full User Profile

Taking the New Swing Tree Table for a Spin

06.04.2008
| 67817 views |
  • submit to reddit
Announcing the new Swing Tree Table yesterday, Tim Boudreau writes:

Usage is incredibly easy - you just provide a standard Swing TreeModel of whatever sort you like, and an additional RowModel that can be queried for the other columns contents, editability and so forth.

I found an example from some time ago, by Tim, and have been playing with it to get used to this new development. The result is as follows:

To get started, I simply download the latest NetBeans IDE development build from netbeans.org and then attached the platform8/org-netbeans-swing-outline.jar to my Java SE project. For the rest, I wasn't required to do anything with NetBeans, necessarily. I could have attached the JAR to a project in Eclipse or anywhere else. Then I created a JFrame.

To work with this Swing tree table, you need to provide the new "org.netbeans.swing.outline.Outline" class with the new "org.netbeans.swing.outline.OutlineModel" which, in turn, is built from a plain old javax.swing.tree.TreeModel, together with the new "org.netbeans.swing.outline.RowModel". Optionally, to change the default rendering, you can use the new "org.netbeans.swing.outline.RenderDataProvider".

Let's first create a TreeModel for accessing files on disk. We will receive the root of the file system as a starting point:

private static class FileTreeModel implements TreeModel {

private File root;

public FileTreeModel(File root) {
this.root = root;
}

@Override
public void addTreeModelListener(javax.swing.event.TreeModelListener l) {
//do nothing
}

@Override
public Object getChild(Object parent, int index) {
File f = (File) parent;
return f.listFiles()[index];
}

@Override
public int getChildCount(Object parent) {
File f = (File) parent;
if (!f.isDirectory()) {
return 0;
} else {
return f.list().length;
}
}

@Override
public int getIndexOfChild(Object parent, Object child) {
File par = (File) parent;
File ch = (File) child;
return Arrays.asList(par.listFiles()).indexOf(ch);
}

@Override
public Object getRoot() {
return root;
}

@Override
public boolean isLeaf(Object node) {
File f = (File) node;
return !f.isDirectory();
}

@Override
public void removeTreeModelListener(javax.swing.event.TreeModelListener l) {
//do nothing
}

@Override
public void valueForPathChanged(javax.swing.tree.TreePath path, Object newValue) {
//do nothing
}

}

The above could simply be set as a JTree's model and then you'd have a plain old standard JTree. It would work, no problems, it would be a normal JTree. However, it wouldn't be a tree table since you'd only have a tree, without a table. Therefore, let's now add two extra columns, via the new "org.netbeans.swing.outline.RowModel" class, which will enable the creation of a tree table instead of a tree:

private class FileRowModel implements RowModel {

@Override
public Class getColumnClass(int column) {
switch (column) {
case 0:
return Date.class;
case 1:
return Long.class;
default:
assert false;
}
return null;
}

@Override
public int getColumnCount() {
return 2;
}

@Override
public String getColumnName(int column) {
return column == 0 ? "Date" : "Size";
}

@Override
public Object getValueFor(Object node, int column) {
File f = (File) node;
switch (column) {
case 0:
return new Date(f.lastModified());
case 1:
return new Long(f.length());
default:
assert false;
}
return null;
}

@Override
public boolean isCellEditable(Object node, int column) {
return false;
}

@Override
public void setValueFor(Object node, int column, Object value) {
//do nothing for now
}

}

Now, after dragging-and-dropping an Outline object onto your JFrame (which is possible after adding the beans from the JAR to the NetBeans IDE Palette Manager) which, in turn, automatically creates a JScrollPane as well, this is how you could code the JFrame's constructor:

public NewJFrame() {

//Initialize the ui generated by the Matisse GUI Builder, which,
//for example, adds the JScrollPane to the JFrame ContentPane:
initComponents();

//Here I am assuming we are not on Windows,
//otherwise use Utilities.isWindows() ? 1 : 0
//from the NetBeans Utilities API:
TreeModel treeMdl = new FileTreeModel(File.listRoots()[0]);

//Create the Outline's model, consisting of the TreeModel and the RowModel,
//together with two optional values: a boolean for something or other,
//and the display name for the first column:
OutlineModel mdl = DefaultOutlineModel.createOutlineModel(
treeMdl, new FileRowModel(), true, "File System");

//Initialize the Outline object:
outline1 = new Outline();

//By default, the root is shown, while here that isn't necessary:
outline1.setRootVisible(false);

//Assign the model to the Outline object:
outline1.setModel(mdl);

//Add the Outline object to the JScrollPane:
jScrollPane1.setViewportView(outline1);

}

Alternatively, without the NetBeans Matisse GUI Builder and NetBeans Palette Manager, i.e., simply using a standard Java class, you could do something like this:

private Outline outline;
public NewJFrame() {

setDefaultCloseOperation(EXIT_ON_CLOSE);

getContentPane().setLayout(new BorderLayout());

TreeModel treeMdl = new FileTreeModel(File.listRoots()[0]);

OutlineModel mdl = DefaultOutlineModel.createOutlineModel(
treeMdl, new FileRowModel(), true);

outline = new Outline();

outline.setRootVisible(false);

outline.setModel(mdl);

getContentPane().add(new JScrollPane(outline),BorderLayout.CENTER);

setBounds(20, 20, 700, 400);

}

At this point, you can run the JFrame, with this result:

So, we see a lot of superfluous info that doesn't look very nice. Let's implement "org.netbeans.swing.outline.RenderDataProvider", as follows:

private class RenderData implements RenderDataProvider {

@Override
public java.awt.Color getBackground(Object o) {
return null;
}

@Override
public String getDisplayName(Object o) {
return ((File) o).getName();
}

@Override
public java.awt.Color getForeground(Object o) {
File f = (File) o;
if (!f.isDirectory() && !f.canWrite()) {
return UIManager.getColor("controlShadow");
}
return null;
}

@Override
public javax.swing.Icon getIcon(Object o) {
return null;

}

@Override
public String getTooltipText(Object o) {
File f = (File) o;
return f.getAbsolutePath();
}

@Override
public boolean isHtmlDisplayName(Object o) {
return false;
}

}

Now, back in the constructor, add the renderer to the outline:

outline1.setRenderDataProvider(new RenderData());

Run the JFrame again and the result should be the same as in the first screenshot above. Look again at the rendering code and note that, for example, you have tooltips:

 

Published at DZone with permission of its author, Geertjan Wielenga.

Comments

Steven Baker replied on Wed, 2008/06/04 - 12:35am

very nice article.

i can see many uses for this new tool. 

David Qiao replied on Wed, 2008/06/04 - 12:56am

Hi Geertjan,

JIDE also has a TreeTable which supports filtering and multiple column sorting. You can run the webstart demo at http://www.jidesoft.com/products/download.htm to see it in action. There is a TreeTable (File System) demo on the left tree. It is the same file system demo as you did. You can also view the source code (there is a view source code button) of the demo. You will find it interesting to compare the two implementations. 

Thanks for the article.

-David

Gustav Weber replied on Sun, 2008/06/08 - 10:51am

Very nice. I wish there were more articles about Swing and Swing Components.

Francis Perreault replied on Fri, 2008/06/13 - 8:26am

Hi Geertjan,

 Echoing a question from Tom Wheeler in Tim's article:

"Is there an easy way to use this with nodes and an ExplorerManager, or is org.openide.explorer.view.TreeTableView still the way to go?"

Thanks!

Francis

Kevin Jaques replied on Sun, 2008/11/30 - 12:20am

It's great you wrote this. I can't find any other material explaining how to use the outline. That said, while the writing might have been fine for an experienced programmer, it's not so good for a newbie. I have spent HOURS on it.

It says to create a "Java SE project". That wasn't the name of any of the templates in Netbeans 6.5. I chose Java:Application, but got no "Design" environment. So then I tried Java:Desktop Application, both as a 'basic' and a 'database'. In neither case was there a JFrame. Instead, there was a FrameView. I gather this automatically creates a JFrame as needed?

 

It says to add the jar to the project. That was especially aggravating in the MacOS, because the jar comes WITHIN the netbeans application, which turns out to be a folder which appears to be a file, called a 'package'. Unfortunately, the Netbeans file browser can't penetrate the package. I had to invent a work-around, making an alias (like a link) to a folder within the package. 

 

It says to create a JFrame. Does that mean create a class that is a JFrame, or create an object which is a JFrame, or just rely on the FrameView to create it as needed?

 

It says to add the TreeModel and the RowModel. When I created classes for them, it said I couldn't make them 'private static'. Research suggested that you must have meant for them to be member classes, but of what? I tried adding them to the FrameView.

 

It says to add code to the JFrame constructor. There isn't one!  I have no idea where to put it.

 

It's 11:30 pm, so I'm going to bed. Maybe I'll wake up with answers. 

 

 

Geertjan Wielenga replied on Sun, 2008/11/30 - 5:31am

Create a Java Application. Then use the JFrame template (in the New File dialog) to create a JFrame. Thanks.

Kevin Jaques replied on Sun, 2008/11/30 - 10:32am

Geertjan wrote me overnight! How great is that! So, for newbies using Netbeans.

1. New project using the "Java:Java Application" Template

2. New class using the "Swing:JFrame" template

3. Add Outline JAR to your Application

a. Control Click "Libraries" in "Projects" pane (under "Window" menu if not showing). Add JAR file.

b. If Mac User, if you have not already done so, create alias so NetBeans can penetrate itself - In Dock, right click Netbeans, choose "Show in Finder". Right-click NetBeans, 'Show Package Contents'. Create alias to 'Contents' Directory (option drag to suitable location). Use that alias when you return to Netbeans

c. Navigate to /[your path to Netbeans application]/NetBeans/NetBeans 6.5.app/Contents/Resources/NetBeans/platform9/modules/org-netbeans-swing-outline.jar. Add it.

4. Add Outline object to your Palette - If you have not already done so, under Tools menu, Palette, choose "Swing/AWT Components", then add the outline.jar, as in 3.c, to the category of your choice.

5. Add Outline object to the JFrame - Show your frame class in the editor pane. Choose 'design' mode. Drag 'outline' from Palette onto the JFrame.

6. Paste the treeModel code into the JFrame Class. Right-click Fix Imports. Right click Format.

7. Paste the rowModel code into the JFrame Class. Right-click Fix Imports. Right click Format.

8. Paste the constructor code  into the JFrame Class. Right-click Fix Imports. Right click Format. NOTE, this must replace the old constructor. Also, the constructor name must match the name of your JFrame class.

9.  in main(), create the JFrame class and show it. For me, that was:

        FileTreeJFrame myFileTreeJFrame = new FileTreeJFrame();

        myFileTreeJFrame.setVisible(true);

10. Run. Isn't that awesome!? Check out how you can re-order & re-size columns and select which to show. You can click column headings to sort! Admire, then quit. 

11.  Add Rendering object. Paste the code into the JFrame Class. Right-click Fix Imports. Right click Format.

12. In the JFrame constructor, add the Renderer to the outline, exactly as Geertjan described.

13. Run. Be even more amazed. Context-dependent colours! Tool tips! Although not shown, it can also do custom icons and show special display names!

14. Note that if you want a cell to be editable, you return true in your rowModel's isCellEditable method.

15. When you figure out how to make it so the outline resizes when you resize the frame, or what the outlineView is for and how it is used, let me know.

Arul Varman replied on Tue, 2008/12/02 - 4:40am

Hi Geertjan,

I have some doubts in using rowmodel for my custom treetable. I am having a checkbox column in 2nd column of treetable and a mouse listener for the outline(treetable). I want to select those checkboxes and I dont know how to do it.

one idea is getting rowmodel from which calling setValuefor() method in mouselistener method. even in this way how to set value for a particular cell in checkbox column.

eagarly waiting for answers.

Pierre Sugar replied on Sat, 2009/01/10 - 12:59am

Hi Geertjan,

thank you for this article. I have been playing around with outline and found this is providing real good functions. But one function I am missing. When adding a new row how can I make outline select the new inserted row?

Thanks and regards

Pierre

 

Tim Boudreau replied on Mon, 2009/01/19 - 10:34pm

Same way as in a regular JTable (Outline extends ETable extends JTable) - 
getSelectionModel().setSelectionInterval (newRow, newRow)

Pierre Sugar replied on Fri, 2009/01/23 - 5:40pm

Hi,

Is there an interface like RowModel that has an effect on the tree nodes in an outline. When I setFullyEditable(true) I can edit the tree nodes but I do not realize when the value has been changed or edited.

Thank you

Pierre

Asaf Jaffi replied on Mon, 2009/03/16 - 8:08am

had a small thing with runnin the tree model: isLeaf could get null nodes...

added:

public boolean isLeaf(Object node) {
if (node == null) return true;

 thanks, asaf :-)

Heiko Wiesner replied on Wed, 2009/03/25 - 8:17am

Hello,

 

thanks for TreeTable - that's missing in JFC Core.

I miss 1 thing in it.

How can i rename nodes?

In a JTree i can set an editor where i can control, if a node is editable or not.

Is there a possibility with Outline?

 

best regards

Asaf Jaffi replied on Sun, 2009/04/05 - 2:31am

ok, some feedback:

the whole selection query is really not that "Usage is incredibly easy - you just provide a standard Swing"...

Outline is a JTable, but the key model is the TreeModel (e.g. look at RowModel's getValueFor(Object node, int column) - it expects a node...).
As such, the current implementation is missing ways to easily convert rows to nodes.
Keep in mind that usually most of the operations on a tree will need a the node's path, so i've expected to see more TreePath query methods.

the way i go about it now, is look at the layout cache (outline.getLayoutCache().getPathForRow(row)).
did i miss something here?
i use Outline out of NetBeans. does the framework have a ready-to-use selection management?

anyway, i'm using this feature in my new app and i like it a lot - thank you for doing this!
asaf :-)

Randy Wigginton replied on Wed, 2009/05/13 - 3:54pm

This TreeTable is so incredibly easy to use and helpful, I cannot possibly thank you enough. Just a couple of minor questions:
1. How do I change the sort symbol to simply be the up or down arrow, getting rid of the "1" next to it. I do not allow more than a single column to be sorted.
2. Is there a way to specify the default sort order on a column? I'd like to start with descending rather than ascending.
3. The version in NetBeans 6.5.1 -- will it be changing significantly in the future? (the javadocs say under development)
Once again, thank you, thank you, thank you!

Bendjamin Stokson replied on Fri, 2010/03/12 - 1:53pm

I have some doubts in using rowmodel for my custom treetable. I am having a checkbox column in 2nd column of treetable and a mouse listener for the outline(treetable). I want to select those checkboxes and I dont know how to do it. one idea is getting rowmodel from which calling setValuefor(stone outdoor fireplaces) method in mouselistener method. even in this way how to set value for a particular cell in checkbox column.

Fotis Paraskevo... replied on Sat, 2010/06/19 - 12:10pm

Hello There, In the hopes of getting an answer, I would like to know, why when the Outline as setRootVisible(false), and no data, an attached mouse listener does not trigger an events! Cheers

Harkey Magar replied on Tue, 2010/10/05 - 12:15am

First of all thanks for a great informative blog post , actually you've tried to make as many users as possible understand what you're trying to say . But there are many person like me who still have very little idea what you spoke on . I think that you should rather use a email marketing software in order to basically get your information or blogs flow in a good rate around the internet market . In this way you can personally help people understand .

Marissa Maples replied on Tue, 2010/11/23 - 2:06am

Virtualization of a server and a set of processes is just an intermediary poor mans step while the innovative research and development goes on in the companies that have a glimpse of the future. If you spent a little more time on the cloud computing forums you would have noted that there are basically two camps - those that want to remove process/storage/memory boundaries and those that want to see the cloud as some large scale server provisioning system (which does not scale at the human side lose weight after pregnancy). I do not understand why you bring up apache httpd when today most application servers that are fronted by such a processes are routinely restarted with the mods dealing with rebinding to instances within the cluster.

Moon Suni replied on Mon, 2011/08/08 - 3:51am

Work with the Swing tree table, you must give the new "org.netbeans.swing.outline.Outline" class with the new "org.netbeans.swing.outline.OutlineModel" which, in turn, is built from a current old javax.swing.tree

Online Directory Listing

Moon Sun replied on Wed, 2011/08/10 - 2:01am

I simply download the latest development build of NetBeans IDE and then connected to my netbeans.org platform8/org-netbeans-swing-outline.jar Java SE project. Otherwise, I do not need to do something NetBeans, necessarily.

guadalajara

Carla Brian replied on Tue, 2012/04/10 - 5:51pm

Thanks for sharing your insights on this. I have a hard time coding about this. Good thing I saw your post. - Instant Tax Solutions Reviews

Steve Sdas replied on Thu, 2012/10/04 - 12:57pm

Therefore, let's now add two extra columns, via the new "org.netbeans.swing.outline.RowModel" class, which will enable the creation of a tree table instead of a tree.best ab workouts for men

Steve Sdas replied on Tue, 2012/10/16 - 5:02am

OutlineModel" which, in turn, is built from a plain old javax.swing.tree.TreeModel, together with the new "org.netbeans.swing.outline.RowModelPPI

Steve Sdas replied on Sat, 2012/10/20 - 7:55am

I would like to thank you for the efforts you had made for writing this awesome articlesadness

Steve Sdas replied on Sun, 2012/10/21 - 1:34pm

The writing style is superior and the content is relevant. Thanks for the insight you provide the readers!estate agents fife

Steve Sdas replied on Mon, 2012/10/22 - 4:07am

Congratulation,,, for making that things possible for your business.drunk driving

Steve Sdas replied on Wed, 2012/10/24 - 3:51am

I find reading this article a joy. It is extremely helpful and interesting and very much looking forward to reading more of your work..pet friendly accommodation

Steve Sdas replied on Fri, 2012/10/26 - 10:16am

RowModel that can be queried for the other columns contents, editability and so forth. Hairdressers Armadale

Steve Sdas replied on Tue, 2012/10/30 - 6:37am

So, we see a lot of superfluous info that doesn't look very nice.3 bureau credit reports and scores

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.