Some time ago I needed some functionality on a JTree that didn’t seem to exist already built in to the TreeSelectionListener that can be added to JTrees. I had to figure out how to reselect elements in a JTree and trigger an event when a node is selected, even though it is already selected.
Considering I couldn’t find a quick way to achieve this with a TreeSelectionListener I thought I would give a brief explaination and example of how this is achieved as it may prove useful to others.
Before we go further, I should point out the differences between using a TreeSelectionListener and a MouseListener.
The TreeSelectionListener will trigger actions based on newly highlighted selections when a node is clicked, the MouseListner will trigger when the mouse is clicked within the JTree wether it is a new selection or not. It is also important to note that highlighting of tree nodes takes place before the listeners are triggered.
So first, as the highlighting of the node takes place before the listener is triggered it doesn’t really matter wether you trigger your action on mousePressed or mouseReleased.
Okay that’s a lie, it does matter. If the user clicks a node and holds the mouse button down the action will trigger straight away. Probably best to you with mouseRelease unless you have other reasons to use mousePressed.
Next we need to know which node we are currently looking at when it comes to triggering the correct action. This is actually really quite simple.
You remember I pointed out that the highlighting of nodes takes place before the listener is triggered? Well the method JTree.getLastSelectedPathComponent() will return a DefaultMutableTreeNode for the currently selected / highlighted node, which has already been updated if a node was clicked.
At this point we have a method that can find the selected node and you can trigger actions within the listener based on the node found.
Now the observant amoung you may have noticed that if you clicked within a JTree but not over one of the nodes then the method above will return the last selected node and would trigger an incorrect action.
This would be undesirable. So we need a check to see if the mouse is currently over the node before we trigger any actions. In order to achieve this we need to get the row bounds for the given node, this can be done with the following methods..
JTree.getRowBounds(int row) // Returns the bounds for a given row JTree.getSelectionRows() //Returns an int[] of selected rows
For this example I am not using multi selection of nodes so we only need the first values of the selected rows. Once we have the bounds of that row we need only check that the mouse coordinates are contained within the bounds, if so then we can trigger the action for the node.
For those who like nice and easy code to just copy and paste the contents of the listener method can be found below.
DefaultMutableTreeNode node = tree.getLastSelectedPathComponent(); if(((JTree) tree.getTree()).getSelectionRows().length!=0){ Rectangle r = ((JTree) tree.getTree()).getRowBounds(((JTree) tree.getTree()).getSelectionRows()[0]); if (node == null || !r.contains(e.getX(), e.getY())) return; } triggerBookmark(node);
If you wish to allow for multiple selection you need only to loop through all selected rows and check for the mouse coordinates within them.
Our software libraries allow you to
Convert PDF to HTML in Java |
Convert PDF Forms to HTML5 in Java |
Convert PDF Documents to an image in Java |
Work with PDF Documents in Java |
Read and Write AVIF, HEIC, WEBP and other image formats |