如何创建弹出菜单

时间:2013-12-17 13:15:52

标签: javafx-2 popupmenu

我是javafx的新手。我想在鼠标右键单击时显示弹出菜单。我找到了一个教程HereHere,但不明白。我想创建弹出菜单,在此链接上显示图像。

现在我正在创造舞台,但我不想舞台。我需要显示右键单击显示的弹出菜单,单击任意位置时关闭。

这是我的代码,其中我正在使用舞台,但我需要打开上面链接的弹出菜单。

 public void MouseClickedOnTree(MouseEvent event) {
if (event.isSecondaryButtonDown()) {

        System.out.println("secondary press");
        final Stage optionstage = new Stage();

        VBox vBox = new VBox(5);
        vBox.setMinHeight(50);
        vBox.setMinWidth(50);
        Button btnNewTestBed = new Button("New Testbed");
        btnNewTestBed.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                try {
                     optionstage.close();
                    stage.show();
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        });
        Button btnOpenTestbed = new Button("Open Testbed");
        btnOpenTestbed.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                optionstage.close();

            }
        });
        optionstage.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ESCAPE) {
                    System.out.println("click on escape");
                    //Stage sb = (Stage) label.getScene().getWindow();//use any one object
                    if(optionstage.isShowing())
                        optionstage.close();
                }
            }
        });

        vBox.getChildren().addAll(btnNewTestBed, btnOpenTestbed);
        optionstage.setScene(new Scene(vBox, 100, 100));
        //stage.setScene(new Scene(new Group(new Text(50,50, "my second window")))); 
        optionstage.setX(event.getSceneX());
        optionstage.setY(event.getScreenY());
        optionstage.initStyle(StageStyle.UNDECORATED);
        optionstage.show();

    }

请提供任何链接或参考。

3 个答案:

答案 0 :(得分:24)

代码的上下文不是很清楚:这是在事件处理程序中吗?如果是这样,它的事件处理程序是什么?如果没有,开场event声明中的if是什么?

您提供的两个链接非常复杂;在JavaFX中(与Swing不同),您应该只考虑将现有Node类子类化为非常高级的用例。只需创建一个弹出菜单,就不需要这种复杂程度。

创建弹出菜单的最简单方法是Control(或子类);您只需要创建一个ContextMenu,添加MenuItem,然后将其设置为您控件上的contextMenu

TextField textField = new TextField("Type Something"); // we will add a popup menu to this text field
final ContextMenu contextMenu = new ContextMenu();
MenuItem cut = new MenuItem("Cut");
MenuItem copy = new MenuItem("Copy");
MenuItem paste = new MenuItem("Paste");
contextMenu.getItems().addAll(cut, copy, paste);
cut.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Cut...");
    }
});
// ...
textField.setContextMenu(contextMenu);

如果您想在非ContextMenu(例如ControlPane)的节点上使用Shape,则您没有一个setContextMenu(...)方法,所以你只需要做一些工作:

final AnchorPane pane = new AnchorPane();
// fill pane with nodes, etc
// create context menu and menu items as above
pane.setOnMousePressed(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        if (event.isSecondaryButtonDown()) {
            contextMenu.show(pane, event.getScreenX(), event.getScreenY());
        }
    }
});

有关详情,请参阅ContextMenu的{​​{3}}或Javadocs

答案 1 :(得分:14)

James_D已经提供了一个与教程一致的工作示例,但我遇到了问题。 James说的是,对于任何类型Control的节点,打开上下文菜单的正确方法是使用Control.setContextMenu()。但是与本教程相反,在非控制节点上注册上下文菜单的正确方法如下(Java 8):

    pane.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
        contextMenu.show(pane, event.getScreenX(), event.getScreenY());
        event.consume();
    });
    pane.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
        contextMenu.hide();
    });

这与幕后的setContextMenu一致。控件的setContextMenu实现使用和使用ContextMenuEvent,但使用鼠标事件。这意味着如果您在窗格上为MouseEvent注册一个侦听器并在窗格中的Control上使用setContextMenu,则右键单击该控件将实际打开两个上下文菜单:当Pane侦听时,Control将侦听并使用ContextMenuEvent并使用MouseEvent。我在openddk-8的代码中发现,在Pane上注册ContextMenuEvent监听器解决了这个重复的上下文菜单问题。

我还发现,当用户点击其他地方时,默认情况下,在窗格上注册的菜单不会被忽略。不使用其事件的MOUSE_PRESSED侦听器可确保在应该删除菜单时将其解除。

答案 2 :(得分:0)

James_D的更高答案是错误的。如果右键单击该非控制窗格,但单击鼠标右键,则上下文菜单不会自动隐藏。

我喜欢FuzzyBSc的答案,但是这一答案更为简洁。两者都会起作用。

pane.setOnContextMenuRequested(e -> 
contextMenu.show(pane, e.getScreenX(), e.getScreenY()));