28

I'm unable to make a JavaFX MenuBar show as a standard OS X menu bar, at the top of the screen.

Here's what I've tried in my subclass of Application:

public void start(Stage primaryStage) throws Exception {
    final Menu menu1 = new Menu("File");
    final Menu menu2 = new Menu("Options");
    final Menu menu3 = new Menu("Help");

    MenuBar menuBar = new MenuBar();
    menuBar.getMenus().addAll(menu1, menu2, menu3);
    menuBar.setUseSystemMenuBar(true);

    primaryStage.setTitle("Creating Menus with JavaFX 2.0");
    final Group rootGroup = new Group();
    final Scene scene = new Scene(rootGroup, 800, 400, Color.WHEAT);


    rootGroup.getChildren().add(menuBar);
    primaryStage.setScene(scene);
    primaryStage.show();
}

I assumed that the use of

menuBar.setUseSystemMenuBar(true);

would do the trick, but actually it makes the menuBar disappear altogether.

I'm using Java 1.8.0-b132 on OS X 10.9

Steve McLeod
  • 51,737
  • 47
  • 128
  • 184

6 Answers6

24

I've had success with this code:

MenuBar menuBar = new MenuBar();
final String os = System.getProperty("os.name");
if (os != null && os.startsWith("Mac"))
  menuBar.useSystemMenuBarProperty().set(true);

BorderPane borderPane = new BorderPane();
borderPane.setTop(menuBar);

primaryStage.setScene(new Scene(borderPane));
Ky -
  • 30,724
  • 51
  • 192
  • 308
dmolony
  • 1,125
  • 9
  • 23
9

It looks like OS X only displays the Menus if they have MenuItems inside them (which is a bit weird, as you can attach functionality to empty Menus).

James_D
  • 201,275
  • 16
  • 291
  • 322
7

I created a little project that gives you access to the auto-generated menu bar on OS X: NSMenuFX

Update: With the new pure JavaFX version, the API has slightly changed

It allows you to replace the default Mac OS menu bar items, so you can to something like this:

// Get the toolkit
MenuToolkit tk = MenuToolkit.toolkit();

// Create default application menu with app name "test"
Menu defaultApplicationMenu = tk.createDefaultApplicationMenu("test");

// Replace the autogenerated application menu
tk.setApplicationMenu(defaultApplicationMenu);

// Since we now have a reference to the menu, we can rename items
defaultApplicationMenu.getItems().get(1).setText("Hide all the otters");

You can of course also add new menu items as you do in your example above.

Jan Gassen
  • 3,406
  • 2
  • 26
  • 44
  • Works nicely but the remark about -XstartOnFirstThread is important because otherwise you won't get it running from inside Eclipse. – mipa Apr 14 '15 at 15:02
  • It looks like your API has changed in the "pure JavaFX" version -- maybe update the answer? – David Moles Feb 25 '16 at 20:12
  • 1
    Thanks for reminding me, the sample code has been updated. You also don't need to care about `-XstartOnFirstThread` anymore. – Jan Gassen Feb 26 '16 at 10:21
3

I just ran into this issue myself - I noticed that the system menubar wouldn't initially appear in OSX until I switched to another application and back.

Wrapping the setUseSystemMenuBar call in a runLater did the trick, so I unscientifically concluded there's more window setup required before OSX can successfully register an application menu.

Platform.runLater(() -> menuBar.setUseSystemMenuBar(true));
BenM
  • 86
  • 3
  • 3
    Did you have any more insight into this? I have a slightly different issue -- when I set useSystemMenuBar to true either programmatically in Java, or from the FXML file, I get the menu bar on the top of the Mac screen, except it doesn't work. I click anywhere in the menu bar and nothing happens. If I switch to another application and then back to my application, it starts working. I tried enclosing the call inside a runLater from my Application.start() method, but same thing. Maybe I'll ask this: where are you calling Platform.runLater() from that it works for you? – Peter Hollemans Dec 06 '19 at 05:34
  • The topic is a bit old, but currently I stumbled over the same problem. Unfortunately the suggested solutions do not work. I also work NSMenuFX, I tried with and without app menu. I tried setting menuBar.setUseSystemMenuBar directly and with async. No change. Does anybody have update for this? I'm using OpenJDK 14 and JavaFX / OpenJFX 15. – Tobi Dec 11 '20 at 08:35
1

Credits to this tutorial that I have followed with success:

https://blog.codecentric.de/en/2015/04/tweaking-the-menu-bar-of-javafx-8-applications-on-os-x/

Below I paste the most important part to get an OS X menu bar compatible with Win classic menu bar:

@Override
public void start(Stage primaryStage) throws Exception {
    MenuBar menuBar = new MenuBar();
    menuBar.useSystemMenuBarProperty().set(true);

    Menu menu = new Menu("java");
    MenuItem item = new MenuItem("Test");

    menu.getItems().add(item);
    menuBar.getMenus().add(menu);

    primaryStage.setScene(new Scene(new Pane(menuBar)));
    primaryStage.show();
}
madx
  • 6,723
  • 4
  • 55
  • 59
  • 2
    This is not the full story. In order to get full compatibility you have to use https://github.com/codecentric/NSMenuFX or otherwise you will still have a bunch of problems, e.g. you cannot internationalize the default menu items. – mipa Aug 01 '19 at 22:13
0

Building on dmolony with some corrections:

MenuBar menuBar = new MenuBar ();
  if( System.getProperty("os.name","UNKNOWN").equals("Mac OS X")) {
  menuBar.setUseSystemMenuBar(true);
}

BorderPane borderPane = new BorderPane ();
borderPane.setTop (menuBar);
primaryStage.setScene (new Scene (borderPane));
nail
  • 1
  • 1