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

时间:2014-05-02 01:04:12

标签: java javafx-8

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

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

在我的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的坐标

1 个答案:

答案 0 :(得分:2)

根本不可能为给定项目提供对单元格的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<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);
    }
}