Pregunta

I am newbie on javafx. I want to show popup menu on Right Mouse click. I find one tutorial Here and Here but don't understand. I want to create popup menu which show in image on this link.

Right now i am creating stage but i don't want stage. I need to show popup menu which show on right click and close when i click anywhere.

Here is my code in which i am using stage but i need to ope popup menu like above link.

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

    }

Please provide me any link or reference.

¿Fue útil?

Solución

The context of your code is not very clear: is this inside an event handler? If so, what's it an event handler for? If not, what is event in the opening if statement?

The two links you provide are pretty complex; in JavaFX (unlike Swing) you should only consider subclassing existing Node classes for pretty advanced use cases. You don't need this level of complexity just to create a popup menu.

The easiest way to create a popup menu is for a Control (or subclass); you just need to create a ContextMenu, add MenuItems to it, and set it as the contextMenu on your control:

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

If you want to use a ContextMenu on a Node that is not a Control (a Pane or a Shape, for example), you don't have a setContextMenu(...) method, so you just need a little more work:

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

See the Javadocs for ContextMenu or the tutorial for more details.

Otros consejos

James_D already provided a working example consistent with the tutorials but I ran into problems with it. James is correct in saying that for any Node of type Control the correct way to open the context menu is to use Control.setContextMenu(). However contrary to the tutorial the correct way to register a context menu on non-Control Nodes is as follows (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();
    });

This is consistent with the what setContextMenu does behind the scenes. The setContextMenu implementation for Controls uses and consumes ContextMenuEvent but does not consume the mouse event. This means that if you register a listener for the MouseEvent on a Pane and use setContextMenu on a Control within the Pane a right click on the control will actually open both context menus: The Control will listen for and consume the ContextMenuEvent while the Pane listens for and consumes the MouseEvent. I found in my code with openjdk-8 that registering a ContextMenuEvent listener on the Pane solved this duplicate context menu problem.

I also found that a menu registered on a Pane does not dismiss by default when the user clicks elsewhere. The MOUSE_PRESSED listener that does not consume its event ensures the menu is dismissed when it should be.

James_D's higher up answer is wrong. If you right click on that non-control pane, but click away, the context menu doesn't autohide.

I like fuzzyBSc's answer, but I've found this combination to work in all edge cases:

pane.setOnContextMenuRequested(e -> contextMenu.show(pane, e.getScreenX(), e.getScreenY()));
pane.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> contextMenu.hide());
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top