A trivial toy application with a screen menu bar can be written like this in Java FX 8:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(final String[] args) throws Exception {
launch(Main.class, args);
}
@Override
public void start(Stage stage) throws Exception {
MenuBar menuBar = new MenuBar();
Menu fileMenu = new Menu("File");
MenuItem newNotebookMenuItem = new MenuItem("New Notebook...");
newNotebookMenuItem.setAccelerator(KeyCombination.keyCombination("Meta+N"));
newNotebookMenuItem.setOnAction(event -> { System.out.println("Action fired"); });
fileMenu.getItems().add(newNotebookMenuItem);
menuBar.getMenus().add(fileMenu);
menuBar.setUseSystemMenuBar(true);
VBox root = new VBox();
root.getChildren().add(menuBar);
Scene scene = new Scene(root, 400, 350);
stage.setScene(scene);
stage.show();
}
}
This might be OK for making toy apps like calculators where there is only one window and the application closes when the last window closes, but my application is document-based. When a document-based application has no documents open, there are no windows open but the menu should remain visible so that the user can open a new document.
The usual way to do this is setDefaultMenuBar
in the com.apple.eawt
APIs, but this is not great because:
Is there a proper way to set this which I just haven't found yet? I expected to find such a method on Application (some mailing list posts were hinting that it might end up there) but it looks like it's still missing.
Currently my trick is as follows:
Pane pane = new Pane();
pane.maxWidth(1);
pane.maxHeight(1);
pane.resize(1, 1);
pane.getChildren().add(menuBar);
Scene scene = new Scene(pane,1,1);
scene.setFill(null);
primaryStage.initStyle(StageStyle.TRANSPARENT);
primaryStage.setWidth(1);
primaryStage.setHeight(1);
primaryStage.setScene(scene);
primaryStage.show();
I don't use this stage for anything. It should appear invisible as well. Annoying & ugly, but it works.
The other sad fact is that I must set any window to have the same menubar.... This may or may not work for you.
Here is another possibility without any scene hacks, yet be aware it uses private APIs:
List<MenuBase> menus = new ArrayList<>();
menus.add(GlobalMenuAdapter.adapt(fileMenu));
Toolkit.getToolkit().getSystemMenu().setMenus(menus);
Important: This is a OS X only solution, so you still need to add your menu to the scene for other operating systems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With