【问题标题】:Disable TreeItem's default expand/collapse on double click (JavaFX 8)双击时禁用 TreeItem 的默认展开/折叠 (JavaFX 8)
【发布时间】:2017-09-26 22:54:31
【问题描述】:

如何在 TreeView 中双击 TreeItem 时禁用默认的展开/折叠行为?

我的问题和这个一模一样:Disable TreeItem's default expand/collapse on double click JavaFX 2.2 不幸的是,提供的答案不再有效(如果他们曾经做过的话)。

更新 1: 不幸的是,我不知道重要的是要提到我不使用标准TreeItem,而是使用经过修改的标准。它的构造函数如下所示:

public BasicTreeItem(String text) {
  super();

  _label = new Label(text);
  stateIndicator = new ImageView();
  this.setToNever(); // sets the stateIndicator mentioned above

  _hb = new HBox();
  this.setValue(_hb);
  _hb.getChildren().add(stateIndicator);
  _hb.getChildren().add(_label);
  _hb.setAlignment(Pos.CENTER_LEFT);
}

所以最后看到的是HBox。

【问题讨论】:

  • 好奇:为什么要更改标准(至少在 win 上)UX?典型的用户对这样的调整并不满意;)
  • 我的 TreeItems 由一个特殊的 CheckBox 组成,它有 4 种不同的状态,我想快速更改它们。如果我在它们上单击得太快,TreeItems 会展开/折叠,这是我不希望的。但是如果我双击标签,我仍然希望项目展开/折叠。
  • 感谢您的信息:)

标签: java javafx treeview javafx-8


【解决方案1】:

例如,您可以使用TreeViewCellFactory 将鼠标侦听器上的EventFilter 附加到树的TreeCells。

示例:

public class TreeViewExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();

        TreeView tw = new TreeView();
        TreeItem rootNode = new TreeItem("Root");
        TreeItem blockOne = new TreeItem("Block1");
        TreeItem childA = new TreeItem("ChildA");
        TreeItem childB = new TreeItem("ChildB");
        blockOne.getChildren().add(childA);
        blockOne.getChildren().add(childB);
        TreeItem blockTwo = new TreeItem("Block2");
        TreeItem childC = new TreeItem("ChildC");
        TreeItem childD = new TreeItem("ChildD");
        blockTwo.getChildren().add(childC);
        blockTwo.getChildren().add(childD);
        rootNode.getChildren().add(blockOne);
        rootNode.getChildren().add(blockTwo);
        tw.setRoot(rootNode);


        tw.setCellFactory(param -> {
            TreeCell<String> treeCell = new TreeCell<String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty) {
                        setText("");
                        setGraphic(null);
                        return;
                    }

                    setText(item.toString());
                }
            };

            treeCell.addEventFilter(MouseEvent.MOUSE_PRESSED, (MouseEvent e) -> {
                if (e.getClickCount() % 2 == 0 && e.getButton().equals(MouseButton.PRIMARY))
                    e.consume();
            });
            return treeCell;
        });

        root.getChildren().add(tw);
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setTitle("TreeView!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

针对您的特定用例的更新:

首先,你的TreeItem 实现真的很奇怪,因为它一定是这样的:

class BasicTreeItem extends TreeItem<HBox>

使用 GUI 元素作为模型是一种不好的做法。您可以实现一个能够存储每个项目可以拥有的所有状态的类,并将该类用作TreeView 的模型以及BasicTreeItem 实现的通用参数。

但要回答更新问题:如果您希望在双击Label 时具有双击展开行为,但如果您不想在双击ImageView 时具有它。

在这种情况下,您可以 r完全删除 CellFactory 并将 EventFilter 添加到 ImageView(例如,在您的 BasicTreeItem 构造函数中):

stateIndicator.addEventFilter(MouseEvent.MOUSE_PRESSED, (MouseEvent e) -> {
    if (e.getClickCount() % 2 == 0 && e.getButton().equals(MouseButton.PRIMARY))
        e.consume();
});

有了这个 fitler 你的TreeItem 将有标准的双击行为,除了双击ImageView

【讨论】:

  • 非常感谢。不幸的是,我忘了提到我使用了自己的 TreeItem 版本,我现在将其添加到原始问题中。如果您知道如何为此setCellFactory,我会非常高兴:)
  • 做到了:)。在我的下一个项目中,我肯定不会再使用 GUI 元素作为模型了,但现在我已经到了很远的地方重新设计所有东西。
  • 为了清楚起见,您所说的“使用 GUI 元素作为模型是一种不好的做法”是什么意思?是因为使用了HBox`` (which is actually just used to show the relevant information in the TreeView` 还是因为我在TreeItem 中存储了数据?基本上我想知道TreeItem 是否会是一个模型,我可以在其中存储数据(通过扩展TreeItemclass),甚至可以使用更多的数据来存储树状结构的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 2017-09-29
  • 2013-09-20
  • 2015-09-08
  • 1970-01-01
  • 2020-07-22
  • 2013-08-09
相关资源
最近更新 更多