在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“笑”。
答案 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)
这是许多程序中菜单的常见行为。我不认为你可以改变它。但是,您可以使用其他一些控件和模拟菜单。 (例如HBox
和Label
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.)以使它们尽可能均匀,并避免由于在同一菜单栏中有不同的节点类型而造成图形不一致。