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.)