I am working on a JavaFX 2.2 project and i want to set custom handling of the mouse (double) click event on a TreeItem. Using treeview.setOnMouseClicked i fire my code without errors but the problem is that the TreeItem, on every mouse double click, it toggles between expanded and collapsed. I suppose that this is the default behavior, but how i disable it??
I had the same issue and solved it in time using EventDispatcher
.
class TreeMouseEventDispatcher implements EventDispatcher {
private final EventDispatcher originalDispatcher;
public TreeMouseEventDispatcher(EventDispatcher originalDispatcher) {
this.originalDispatcher = originalDispatcher;
}
@Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
if (event instanceof MouseEvent) {
if (((MouseEvent) event).getButton() == MouseButton.PRIMARY
&& ((MouseEvent) event).getClickCount() >= 2) {
if (!event.isConsumed()) {
// Implement your double-click behavior here, even your
// MouseEvent handlers will be ignored, i.e., the event consumed!
}
event.consume();
}
}
return originalDispatcher.dispatchEvent(event, tail);
}
}
and then use this TreeMouseEventDispatcher
for the TreeCell
:
treeView.setCellFactory(new Callback<TreeView<T>, TreeCell<T>>() {
@Override
public TreeCell<T> call(TreeView<T> param) {
return new TreeCell<T>() {
@Override
protected void updateItem(T item, boolean empty) {
if (item != null && !empty) {
EventDispatcher originalDispatcher = getEventDispatcher();
setEventDispatcher(new TreeMouseEventDispatcher(originalDispatcher));
}
}
};
}
}
Turns out that though Bolg's answer works, it isn't strictly the "correct" way to do it, and may cause some unexpected behaviour.
The cause of this issue is described in this bug. To summarise: the default double click behaviour of a tree cell is actually precipitated by the mouse press event, so it's too late to consume the event and block it within a mouse click listener.
The reason the accepted answer works is that it doesn't filter on the mouse event type, meaning it consumes all mouse events relating to the primary button and a click count of two. This also means that the user action is processed three times, which is probably not the intended behaviour.
The fix is only a single line change to Bolg's answer, but I think it is probably better not to involve an EventDispatcher. Something like the following should work just fine:
node.addEventHandler(MouseEvent.ANY, event -> {
if (event.getClickCount() == 2 && event.getButton().equals(MouseButton.PRIMARY)) {
if (event.getEventType().equals(MouseEvent.MOUSE_CLICKED)) {
System.out.println("hello"); // perform some action
}
event.consume();
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With