Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable TreeItem's default expand/collapse on double click JavaFX 2.2

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??

like image 468
Georgios Syngouroglou Avatar asked Mar 19 '13 19:03

Georgios Syngouroglou


2 Answers

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));
        }
      }
    };
  }
}
like image 55
Jan Kubovy Avatar answered Oct 01 '22 12:10

Jan Kubovy


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();
    }
});
like image 26
Elias Vasylenko Avatar answered Oct 01 '22 14:10

Elias Vasylenko