Show context menu using keyboard for TreeCell

后端 未结 1 2043
轻奢々
轻奢々 2021-01-24 11:54

I\'ve tried everything. I think they made a big mistake not giving any reference to the indexed cell in anything.

I can get my menu, but not in the right place. Right

1条回答
  •  無奈伤痛
    2021-01-24 12:37

    It simply isn't possible to provide API access to the cell for a given item. Not every item has a cell associated with it. On top of that, the item which is represented by a cell may change at any time, so even if you could provide access to the cell, the API would potentially be very confusing.

    The basic trick to anything like this is to create a cell factory, and register the appropriate listeners with the cell. Your case is somewhat tricky, but possible. The following works to get the cell representing the selected item (you may want to modify the code somewhat to deal with the case where the cell is scrolled off the screen).

    (Note that I used the Z key, arbitrarily, as I don't have a ContextMenu key on my laptop.)

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

    0 讨论(0)
提交回复
热议问题