CheckboxTree is an open source, Swing-based tree component with a checkbox in each of its nodes, similar to those commonly found in installers but missing from the Swing GUI toolkit. In this article creators Lorenzo Bigagli and Enrico Boldrini introduce CheckboxTree and demonstrate its standout features, namely four configurable check-propagation styles, grayed checkboxes, and a custom renderer that allows you to display radio buttons rather than checkboxes in your tree layouts. The article includes the source code for CheckboxTree, which you may use or extend for your Swing GUI development projects.
Installation GUIs and application preference windows often feature checkbox-enabled tree components, but you won't find such a component in the Swing GUI toolkit. Most developers either end up extending the Swing JTree
ad-hoc or using one of the tree extensions available. We actually tried several of these components for a recent project but found that none of them had quite the features, simplicity or flexibility we needed.
Some components were part of an overly complicated widget library or required extending specific classes that disrupted our class hierarchy design. Some were not open source or relied on libraries that were not open source. Some had native dependencies. Most important, we needed a component that would support several checkbox propagation styles in a tree layout. We also wanted grayable checkboxes to indicate if descendants of a given node were in the opposite checking state from that node. So, like many developers before us, we created our CheckboxTree
component from scratch.
CheckboxTree
is a Swing JTree
component with a checkbox in each of its nodes, as shown in Figure 1 (click the image for a live demonstration).
In this article we introduce CheckboxTree
and explain its relationship to the Swing JTree
classes. We also discuss its architecture and provide implementation details. Finally, we highlight some of the current limitations of CheckboxTree
and note improvements that could be made to it in the future. CheckboxTree
is available under the GPL license, so you are free to use it in your Swing development projects.
Background: JTree concepts and terminology
Before we begin describing CheckboxTree
in detail, it might be helpful to quickly recall some Swing JTree
concepts and terminology:
- JTree, as described in the Swing documentation, is a "control that displays a set of hierarchical data as an outline."
- A node is the basic unit of data displayed by a
JTree
. A specific node can be identified either by aTreePath
or by its display row. - TreePath is an object that contains a
JTree
node and all its ancestors. - TreeModel is an object that manages the
JTree
data model based on the well-known MVC design pattern. - TreeSelectionModel is an object that manages user selections in a
JTree
, typically rendered by highlighting selected nodes. - TreeCellRenderer is used to style
JTree
nodes according to their content and status.
Using CheckboxTree
A key feature of CheckboxTree
is that it does not require you to use tree nodes that implement a specific "checkable-node" interface (e.g., an interface with a method isChecked
). You can continue to work with your preferred tree model, such as the default TreeModel
or a custom one, which makes it easier to integrate CheckboxTree
into your existing code.
You can use CheckboxTree
by invoking one of the provided constructors, which are modeled after the standard JTree
ones. The sample below shows how you would construct a CheckboxTree
with a default TreeModel
.
CheckboxTree checkboxTree = new CheckboxTree();
Here is how you would construct a CheckboxTree
from an existing TreeNode
:
TreeNode yourRoot = new DefaultMutableTreeNode("foo"); CheckboxTree checkboxTree = new CheckboxTree(yourRoot);
Here is how you would construct a CheckboxTree
from an existing TreeModel
:
Model yourTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode("foo")); CheckboxTree checkboxTree = new CheckboxTree(yourTreeModel);
You could also set the data model at a later time, as shown here:
Model yourNewTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode("bar")); checkboxTree.setModel(yourNewTreeModel);
Once constructed, your CheckboxTree
is ready to listen for user input and respond.