Как создать всплывающее меню

Я новичок на javafx. Я хочу показать всплывающее меню в правой клавише мыши. Я нахожу один учебник здесь и здесь, но не понимаю. Я хочу создать всплывающее меню, которое отображается на изображении по этой ссылке.

Сейчас я создаю сцену, но мне не нужна сцена. Мне нужно показать всплывающее меню, которое отображается по щелчку правой кнопкой мыши и закрывается, когда я нажимаю в любом месте.

Вот мой код, в котором я использую сцену, но мне нужно открыть всплывающее меню, как показано выше.

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

    }

Пожалуйста, предоставьте мне ссылку или ссылку.

Ответ 1

Контекст вашего кода не очень ясен: это внутри обработчика событий? Если да, для чего это обработчик событий? Если нет, то что 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 в Node, который не является Control (a Pane или 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());
        }
    }
});

Подробнее см. Javadocs для ContextMenu или .

Ответ 2

James_D уже предоставил рабочий пример, соответствующий учебникам, но у меня возникли проблемы с ним. Джеймс прав, говоря, что для любого Node типа 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 на панели и используете setContextMenu в элементе управления на панели, правый щелчок на элементе управления фактически откроет оба контекстных меню: элемент управления будет прослушивать и использовать ContextMenuEvent, пока панель прослушивает и потребляет MouseEvent. Я нашел в своем коде с openjdk-8, что регистрация слушателя ContextMenuEvent на панели разрешила эту проблему с дублирующимся контекстным меню.

Я также обнаружил, что меню, зарегистрированное на панели, не отменяется по умолчанию, когда пользователь щелкает в другом месте. Слушатель MOUSE_PRESSED, который не потребляет свое событие, гарантирует, что меню будет отклонено, когда это будет.