Java on MacOS: A default Mac menubar without a JFrame

Yesterday I ran into a pretty obscure situation in my Imagen application where I needed to show a modified Mac menubar, even though I didn't have a Java JFrame displayed at the time. The way Imagen works is that I show a JFrame, then hide it, and the application then waits for the user to do something with the application icon in the Mac Dock, typically dropping an image onto that icon.

However, as I was added new functionality to my Java application last night, I realized I wanted Imagen to have menu items showing in the Mac menubar even when the application was in this state of not having a visible JFrame. I didn't know if it could be done, until I discovered the 'setDefaultMenuBar' method in the Mac Application class.

In short, all you have to do is create a JMenuBar like usual, then add that JMenuBar to the Mac menubar using this setDefaultMenuBar method of the Application class. I won't go into great detail about how to do this, but I will share my code. Here's part of the constructor for my Imagen application:

public Imagen()
{
  // sets up the mac dock event stuff
  Application myApplication = Application.getApplication();
  DockBarAdapter dockBarAdapter = new DockBarAdapter(this);
  myApplication.addApplicationListener(dockBarAdapter);

  // handle about, preferences, and quit
  MacOSXApplicationAdapter macAdapter = new MacOSXApplicationAdapter(this);
  myApplication.addApplicationListener(macAdapter);
  
  // add a 'default' menubar
  myApplication.setDefaultMenuBar(createMenusAndActions());
  
  // must enable the preferences option manually if wanted
  //theApplication.setEnabledPreferencesMenu(true);

  // create the initial jframe, then hide it
  baseFrame = createNewFrameAction();
  SwingUtilities.invokeLater(new Runnable()
  {
    public void run()
    {
      baseFrame.setVisible(false);
    }
  });
}

The menubar is created by the createMenusAndActions() method, which looks like this:

private JMenuBar createMenusAndActions()
{
  // build our actions
  screenshotAction = new ScreenshotAction(this, "Take Screenshot", screenshotKeystroke);
  copyToClipboardAction = new CopyToClipboardAction(this, "Copy Image to Clipboard", copyToClipboardKeystroke);

  // create the menubar
  menuBar = new JMenuBar();
  
  // create the File menu
  fileMenu = new JMenu("File");

  // create menu items
  screenshotMenuItem = new JMenuItem(screenshotAction);
  copyToClipboardMenuItem = new JMenuItem(copyToClipboardAction);
  
  // add menu items to the menu
  fileMenu.add(screenshotMenuItem);
  fileMenu.add(copyToClipboardMenuItem);

  // add menu to the mac menubar
  menuBar.add(fileMenu);
  return menuBar;
}

Create a Java application on the Mac OS X platform that needs a menubar without a JFrame being displayed is a pretty obscure situation, so I won't write any more about this here today. I just wanted to share an example to show that if you ever find yourself in this situation, it is possible to alter the Mac menubar without a JFrame.