例如,您可以使用TreeView 的CellFactory 将鼠标侦听器上的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。