禁用JavaFX 2.2中TreeItem默认的双击展开/折叠功能

5

我正在开发一个JavaFX 2.2项目,想要对TreeItem的鼠标(双击)点击事件进行自定义处理。使用treeview.setOnMouseClicked可以在没有错误的情况下触发我的代码,但问题是每次鼠标双击时,TreeItem都会在展开和折叠之间切换。我想这是默认行为,但我该如何禁用它?


在……之前尝试查看论坛。 - Perco
我的问题不是鼠标点击事件的检测,而是TreeItem的默认双击行为。通过使用treeview.setOnMouseClicked方法可以轻松检测到该事件,但这并不是我要寻找的。TreeItem默认情况下会在双击时展开或折叠自身,这就是我的问题所在。我希望禁用这一默认行为。 - Georgios Syngouroglou
2个回答

4

我曾经遇到同样的问题,但是使用 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);
    }
}

然后为TreeCell使用TreeMouseEventDispatcher

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));
        }
      }
    };
  }
}

谢谢 - 我也不得不使用这个! - CMerrill
这个答案只是偶然起作用了!因为它在另一方面出现了问题。我会添加另一个答案来解释这个问题。 - Elias Vasylenko

2
原来Bolg的答案虽然可行,但并不是“正确”的方法,可能会导致一些意外的行为。这个问题的原因在于这个bug中有所描述。总结一下:树单元格的默认双击行为实际上是由鼠标按下事件引发的,因此在鼠标点击侦听器中消耗事件和阻止它已经太迟了。
接受的答案之所以有效,是因为它没有过滤鼠标事件类型,这意味着它消耗所有与主按钮和点击计数为2相关的鼠标事件。这也意味着用户操作被处理了三次,这可能不是预期的行为。
修复只需要对Bolg的答案进行一行更改,但我认为最好不要涉及EventDispatcher。像下面这样做应该就可以了:
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();
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接