【问题标题】:How to create popup menu如何创建弹出菜单
【发布时间】:2013-12-17 13:15:52
【问题描述】:

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

    }

请提供任何链接或参考。

【问题讨论】:

    标签: javafx-2 popupmenu


    【解决方案1】:

    您的代码上下文不是很清楚:这是在事件处理程序中吗?如果是这样,它是什么事件处理程序?如果不是,那么开头的if 语句中的event 是什么?

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

    创建弹出菜单最简单的方法是使用Control(或子类);您只需要创建一个ContextMenu,将MenuItems 添加到其中,并将其设置为您的控件上的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);
    

    如果你想在不是Control 的节点上使用ContextMenu(例如PaneShape),你没有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 了解ContextMenututorial 了解更多详情。

    【讨论】:

    • 但我想在树视图上显示它。当我右键单击树视图时,我想在树视图上显示弹出窗口
    • 我使用此代码但弹出窗口未显示contextMenu.show(soariteTree, event.getScreenX(), event.getScreenY());
    • 对不起..它现在可以工作了....我把声明代码放在事件之外然后它工作了...谢谢..
    • TreeView 是一个控件,所以你可以只做 treeView.setContextMenu(contextMenu);无需注册鼠标处理程序或调用 show(...)
    • ContextMenu中有ResourceBundle的例子
    【解决方案2】:

    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 的侦听器并在窗格内的控件上使用 setContextMenu,则右键单击控件实际上将打开两个上下文菜单:控件将侦听并使用 ContextMenuEvent 而窗格侦听并消耗 MouseEvent。我在使用 openjdk-8 的代码中发现,在窗格上注册 ContextMenuEvent 侦听器解决了这个重复的上下文菜单问题。

    我还发现,当用户单击其他地方时,默认情况下在窗格上注册的菜单不会关闭。不使用其事件的 MOUSE_PRESSED 侦听器可确保在应关闭菜单时关闭菜单。

    【讨论】:

    • Node中还有一个setOnContextMenuRequested()方法
    【解决方案3】:

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

    我喜欢fuzzyBSc 的答案,但这个更简洁。两者都会起作用。

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

    【讨论】:

      猜你喜欢
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      相关资源
      最近更新 更多