使用键盘为TreeCell显示上下文菜单

我已经尝试了一切。 我认为他们犯了一个大错误,没有在任何事情中提供索引单元格的任何参考。

我可以拿到我的菜单,但不是在正确的地方。 右键单击很好。

在我的TreeView中,我可以使用get KeyReleased,但我不知道在哪里放菜单。

setOnKeyReleased((KeyEvent t) -> { switch (t.getCode()) { case CONTEXT_MENU: getSelectionModel().getSelectedItem().setGraphic(new Label("hi")); //showMenu just calls show on my ContextMenu of my subclass TreeNode ((TreeNode)getSelectionModel().getSelectedItem()).showMenu( getSelectionModel().getSelectedItem().getGraphic().getLocalToSceneTransform()); break; } }); 

没有任何布局方法会给我TreeCell的坐标

对于给定项目,无法为单元格提供API访问。 并非每个项目都有与之关联的单元格。 最重要的是,由单元格表示的项目可能随时更改,因此即使您可以提供对单元格的访问,API也可能非常混乱。

这样的基本技巧是创建一个单元工厂,并向单元注册适当的监听器。 你的情况有点棘手,但可能。 以下工作来获取表示所选项目的单元格(您可能需要稍微修改代码以处理单元格从屏幕滚动的情况)。

(请注意,我任意使用Z键,因为我的笔记本电脑上没有ContextMenu键。)

 import javafx.application.Application; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; import javafx.geometry.Bounds; import javafx.geometry.Point2D; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.input.KeyCode; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage primaryStage) { try { BorderPane root = new BorderPane(); TreeView treeView = new TreeView<>(); TreeItem treeRoot = new TreeItem<>("Root"); for (int i=1; i<=5; i++) { TreeItem child = new TreeItem<>("Item "+i); child.getChildren().addAll(new TreeItem<>("Item "+i+"A"), new TreeItem<>("Item "+i+"B")); treeRoot.getChildren().add(child); } treeView.setRoot(treeRoot); root.setCenter(treeView); ObjectProperty> selectedCell = new SimpleObjectProperty<>(); treeView.setCellFactory(tree -> { TreeCell cell = new TreeCell<>(); cell.textProperty().bind(cell.itemProperty()); ChangeListener> listener = (obs, oldItem, newItem) -> { TreeItem selectedItem = treeView.getSelectionModel().getSelectedItem(); if (selectedItem == null) { selectedCell.set(null); } else { if (selectedItem == cell.getTreeItem()) { selectedCell.set(cell); } } }; cell.treeItemProperty().addListener(listener); treeView.getSelectionModel().selectedItemProperty().addListener(listener); return cell ; }); ContextMenu contextMenu = new ContextMenu(); for (int i=1; i<=3; i++) { String text = "Choice "+i; MenuItem menuItem = new MenuItem(text); menuItem.setOnAction(event -> System.out.println(text)); contextMenu.getItems().add(menuItem); } treeView.setOnKeyReleased(event -> { if (event.getCode() == KeyCode.Z) { if (selectedCell.get() != null) { Node anchor = selectedCell.get(); // figure center of cell in screen coords: Bounds anchorBounds = anchor.getBoundsInParent(); double x = anchorBounds.getMinX() + anchorBounds.getWidth() / 2 ; double y = anchorBounds.getMinY() + anchorBounds.getHeight() / 2 ; Point2D screenLoc = anchor.getParent().localToScreen(x, y); contextMenu.show(selectedCell.get(), screenLoc.getX(), screenLoc.getY()); } } }); Scene scene = new Scene(root,400,400); primaryStage.setScene(scene); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }