In general I don't want that a collapsed node is automatically selected. Instead I want its child-node to stay selected, when it was selected previously.
In the example below expand "Fruits" and then select "banana". Now collapse "Fruits" by clicking on the collapse icon left of the "Fruits" node's icon. The "Fruits" node collapses, and is also selected now.
I want the "banana" node to stay selected also after the "Fruits" node has been collapsed. How can I accomplish this?
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
public class TreeExample extends JFrame
{
private final JTree tree;
public TreeExample()
{
//create the root node
final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
//create the child nodes
final DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
final DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
final DefaultMutableTreeNode aNode = new DefaultMutableTreeNode("apple");
final DefaultMutableTreeNode bNode = new DefaultMutableTreeNode("banana");
final DefaultMutableTreeNode cNode = new DefaultMutableTreeNode("coconut");
final DefaultMutableTreeNode dNode = new DefaultMutableTreeNode("date");
fruitNode.add(aNode);
fruitNode.add(bNode);
fruitNode.add(cNode);
fruitNode.add(dNode);
//add the child nodes to the root node
root.add(vegetableNode);
root.add(fruitNode);
//create the tree by passing in the root node
this.tree = new JTree(root);
this.add(this.tree);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("JTree Example");
this.pack();
this.setVisible(true);
}
public static void main(final String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new TreeExample();
}
});
}
}
Since it seems like it is not possible to have a node selected unless it is visible, I came up with this solution. After debugging into the events, I found that the tree is always "invalid" when I collapse a node. So I override fireValueChange() in JTree. If the tree is "valid" I let the value change happen. Otherwise I clear the selection. If I don't clear the selection, the collapsed node is selected in UI, which gives the wrong impression, since it isn't logically selected. By clearing the selection it is then possible to explicitly select the collapsed node. This solution is closest to what I want. Only thing missing is the invisible node being selected if I expand the previously collapsed node again.
So far it works well for me:
this.tree = new JTree(this.rootNode)
{
@Override
protected void fireValueChanged(final TreeSelectionEvent e)
{
if (this.isValid())
super.fireValueChanged(e);
else
{
super.clearSelection();
}
}
};