我已经尝试了一切。我认为他们犯了一个大错误,就是在任何情况下都未引用索引单元格。
我可以得到菜单,但位置不正确。右键单击即可。
在我的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也会非常混乱。
进行此类操作的基本技巧是创建一个单元工厂,并向该单元注册适当的侦听器。您的情况有些棘手,但可能。下面的工作来获取代表所选项目的单元格(您可能需要对代码进行一些修改以处理单元格从屏幕上滚动出来的情况)。
(请注意,由于我的笔记本电脑上没有ContextMenu键,因此我随意使用了Z键。)
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<String> treeView = new TreeView<>(); TreeItem<String> treeRoot = new TreeItem<>("Root"); for (int i=1; i<=5; i++) { TreeItem<String> 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<TreeCell<String>> selectedCell = new SimpleObjectProperty<>(); treeView.setCellFactory(tree -> { TreeCell<String> cell = new TreeCell<>(); cell.textProperty().bind(cell.itemProperty()); ChangeListener<TreeItem<String>> listener = (obs, oldItem, newItem) -> { TreeItem<String> 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); } }