Creating TreeTables in Swing Note: please also see part 2 and part 3 for further updates of TreeTable By Philip Milne A TreeTable is a combination of a Tree and a Table -- a component capable of both expanding and contracting rows, as well as showing multiple columns of data. The Swing package does not contain a JTreeTable component, but it is fairly easy to create one by installing a JTree as a renderer for the cells in a JTable. This article explains how to use this technique to create a TreeTable. It concludes with a example application, namedTreeTableExample0, which displays a working TreeTable browser that you can use to browse a local file system (see illustration).
In Swing, the JTree, JTable, JList, and JComboBox components use a single delegate object called acell renderer to draw their contents. A cell renderer is a component whosepaint() method is used to draw each item in a list, each node in a tree, or each cell in a table. A cell renderer component can be viewed as a "rubber stamp": it's moved into each cell location usingsetBounds(), and is then drawn with the component'spaint() method. By using a component to render cells, you can achieve the effect of displaying a large number of components for the cost of creating just one. By default, the Swing components that employ cell renderers simply use a JLabel, which supports the drawing of simple combinations of text and an icon. To use any Swing component as a cell renderer, all you have to do is create a subclass that implements the appropriate cell renderer interface: TableCellRenderer for JTable, ListCellRenderer for JList, and so on. Rendering in SwingHere's an example of how you can extend a JCheckBox to act as a renderer in a JTable:
How the example program worksThe code snippet shown above -- part of a sample program presented in full later in this article -- shows how to use a JTree as a renderer inside a JTable. This is a slightly unusual case because it uses the JTree to paint a single node in each cell of the table rather than painting a complete copy of the tree in each of the cells.
As each cell is painted, the JTable goes through the usual process of getting the renderer, setting its bounds, and asking it to paint. In this case, though, we record the row number of the cell being painted in an instance variable namedvisibleRow. We also overridesetBounds(), so that the JTree remains the same height as the JTable, despite the JTable's attempts to set its bounds to fit the dimensions of the cell being painted. To complete this technique we override paint(), making use of the stored variable visibleRow, an operation that effectively moves the clipping rectangle over the appropriate part of the tree. The result is that the JTree draws just one of its nodes each time the table requests it to paint. In addition to installing the JTree as a renderer for the cells in the first column, we install the JTree as the editor for these cells also. The effect of this strategy is the JTable then passes all mouse and keyboard events to this "editor" -- thus allowing the tree to expand and contract its nodes as a result of user input. Example: A file-system browserThe example program presented with this article creates and implements a browser for a file system. Each directory can be expanded and collapsed. Other columns in the table display important properties of files and directories, such as file sizes and dates.
Here is the full list of classes used in the example program, along with a brief description of what each class does (you can download or view each file by clicking its link):
CaveatsFor clarity, we have kept the TreeTableExample0 program short. To be complete, a full-featured JTreeTable component would have to deal with a number of other issues. Here are some features that are missing from this chapter's sample program:
http://java.sun.com/products/jfc/tsc/articles/treetable1/
|