4

I'm struggling to implement the application menu bar correctly in a JavaFX application that runs on MacOS.

As of JDK9, is seems that the supported way to set up the application menu correctly on a Mac is to:

1) package the app with javapackager tool.

2) provide event handlers for the About/Preferences/FileOpen/Print/ etc. events via the API's in the java.awt.desktop package.

(I discovered the hard way that one must first obtain the singleton desktop instance from the main thread, not from a JavaFX thread, or the event handlers provided are ignored.)

3) Set the useSystemMenuBar to move the the main stage's menu bar up in to the Apple system menu.

My problem is that 2) and 3) seem to be incompatible with one another. That is, EITHER i can move menu bar into the system menu bar, OR i can handle the About/Prefs events, bu not both:

import javafx.fxml.FXML
import javafx.fxml.FXMLLoader
import javafx.scene.Scene
import javafx.scene.control.MenuBar
import javafx.scene.layout.Pane
import javafx.stage.Stage

class Controller()
{
  @FXML var menubar: MenuBar = _

  def initialize(): Unit = menubar.setUseSystemMenuBar(true) // EITHER THIS
}

class Menu extends javafx.application.Application
{
  def start(stage: Stage): Unit =
  {
    val l = new FXMLLoader(getClass.getResource(s"/menu.fxml"))

    stage.setScene(new Scene(l.load[Pane]))
    stage.setTitle("Menu")
    stage.show()
  }
}

object Main
{
  def main(args: Array[String]) =
  {
    val d= java.awt.Desktop.getDesktop // OR THIS

    javafx.application.Application.launch(classOf[Menu], args: _*)
  }
}

What's going on here?

The documentation available online (from Apple, form Oracle, etc) is inconstant, fragmented, and generally not much help.

(I'm aware of Jay Gassen's NSMenuFX library, and while it's great, I don't think is a viable long term solution: it uses reflection to reach into the underlying Glass system to chuck the default menu bar supplied by the Apple runtime and monkey with the system menu directly - I would expect this method to fail in a forthcoming release of the JDK (release 10?) when reflection on inaccessible classes will no longer be allowed by the JVM runtime module system.)

  • At least I can assure you that NSMenuFX still works including the latest JDK 11ea+3 version. – mipa Mar 11 '18 at 18:03
  • @mipa: even when the calling client code no longer executes in the unnamed module? i believe this exactly the sort of thing the new module system is designed to prevent... – Jonathon Bell Mar 13 '18 at 15:54
  • I haven't tried that. – mipa Mar 13 '18 at 21:48
  • Have you made any progress on this? I am having the same issue. I'm trying to create a JavaFX app for macOS using Java12, and NSMenuFX won't work. Currently I can't even get an About menu item to even show up in the App menu. – vewert Jan 27 '20 at 23:17
  • Similar: [*How to have a menu on the mac top toolbar with JavaFX?*](https://stackoverflow.com/q/53126884/642706) and [*JavaFX under Mac OS X: System-Menu and modal windows*](https://stackoverflow.com/q/49387966/642706) – Basil Bourque Aug 06 '23 at 18:40

0 Answers0