如何在javafx中禁用右键单击菜单

时间:2018-01-25 08:20:54

标签: javafx menu

在javaFX代码中,可以通过左键单击或右键单击弹出菜单。如何禁用右键单击?

public void start(Stage primaryStage)
{
    BorderPane root = new BorderPane();
    MenuBar menuBar = new MenuBar();

    Menu hello = new Menu("hello");
    menuBar.getMenus().addAll(hello);
    Menu world = new Menu("world");
    menuBar.getMenus().addAll(world);
    root.setCenter(menuBar);

    MenuItem item = new MenuItem("laugh");
    hello.getItems().add(item);
    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);

    primaryStage.show();
}

当我右键单击“你好”菜单时,会弹出menuitem“笑”。

3 个答案:

答案 0 :(得分:2)

基本方法是在MenuBar上注册一个eventFilter,它消耗不应传递给子节点的事件。

在您的应用程序代码中手动执行此操作:

public class DisableRightClickOpenMenu extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane root = new BorderPane();
        MenuBar menuBar = new MenuBar();

        menuBar.addEventFilter(MouseEvent.MOUSE_PRESSED, ev -> {
            if (ev.getButton() == MouseButton.SECONDARY) {
                ev.consume();
            }
        });

        Menu hello = new Menu("hello");
        menuBar.getMenus().addAll(hello);
        Menu world = new Menu("world");
        menuBar.getMenus().addAll(world);
        root.setCenter(menuBar);

        MenuItem item = new MenuItem("laugh");
        hello.getItems().add(item);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);

        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

如果您想在所有应用程序中使用此行为,可以实现一个自定义menuBarSkin,它注册过滤器并通过样式表安装自定义皮肤。

皮肤:

public class ExMenuBarSkin extends MenuBarSkin {

    /**
     * Instantiates a skin for the given MenuBar. Registers an
     * event filter that consumes right mouse press.
     *  
     * @param menuBar
     */
    public ExMenuBarSkin(MenuBar menuBar) {
        super(menuBar);
        menuBar.addEventFilter(MouseEvent.MOUSE_PRESSED, ev -> {
            if (ev.getButton() == MouseButton.SECONDARY) {
                ev.consume();
            }
        });

    }

}

在样式表中(替换为完全限定的类名):

.menu-bar {
     -fx-skin: "de.swingempire.fx.event.ExMenuBarSkin";

}

其用法(用样式表文件名替换名称):

URL uri = getClass().getResource("contextskin.css");
primaryStage.getScene().getStylesheets().add(uri.toExternalForm());

答案 1 :(得分:0)

这是许多程序中菜单的常见行为。我不认为你可以改变它。但是,您可以使用其他一些控件和模拟菜单。 (例如HBoxLabel s。。

答案 2 :(得分:0)

我同意,据我所知,没有标准的方法可以做到这一点,但您可能需要考虑以下解决方法。

它正在用一个由HBox和一个Label组成的Menu对象替换Menu节点:一个EventHandler被添加到HBox中,通过检查按下的鼠标按钮,我们将MenuItem添加/删除到其父节点。

@Override
public void start(final Stage primaryStage) {
    final BorderPane root = new BorderPane();
    final MenuBar menuBar = new MenuBar();
    final Menu menuHello = new Menu();
    final Menu menuWorld = new Menu("world");
    final MenuItem menuitem = new MenuItem("laugh");
    final HBox hbox = new HBox();

    menuBar.getMenus().addAll(menuHello, menuWorld);

    root.setCenter(menuBar);

    hbox.setPrefWidth(30);
    hbox.getChildren().add(new Label("hello"));

    menuHello.setGraphic(hbox);
    menuHello.getItems().add(menuitem);

    hbox.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
        @Override
        public void handle(final MouseEvent e) {
            if (e.getButton() == MouseButton.SECONDARY) {
                System.out.println("Right click");
                menuHello.getItems().remove(menuitem);
            } else {
                System.out.println("Left click");
                if (!menuHello.getItems().contains(menuitem)) {
                    menuHello.getItems().add(menuitem);
                    menuHello.show(); // The .show method prevent 'losing' the current click                    }
            }
        }
    });

    final Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);

    primaryStage.show();
}

这将产生以下结果 - preview

请注意,我只是习惯使用HBox,没有特别的原因。

在使用这样的解决方法时,我的建议是用相同的“模式”填充所有菜单,例如我的示例中的HBox + Label组合,并通过css / code(宽度/高度,背景)对它们进行样式化/ fill / hover ... colors etc.)以使它们尽可能均匀,并避免由于在同一菜单栏中有不同的节点类型而造成图形不一致。