4

I have a simple java swing application. It's mostly used on Macos, so I'm trying to add a default menu bar to it through Desktop.getDesktop().setDefaultMenuBar(...). I defined a menu bar with a "File" menu and a "New" menu item with an action listener. Using the mouse to click on File->New calls the listener's actionPerformed() event as expected.

I tried to attach the standard accelerator to the menu item (Command-N on a mac). Clicking on the "File" menu now displays "New" with the expected accelerator next to it. However, when I actually type Command-N, the action listener isn't called. The only visible effect of typing Command-N is that the "File" menu item briefly flickers.

Edit: This seems to be related to the fact the menu is being set through Desktop.setDefaultMenuBar(). If I attach the menu to the JFrame, then accelerators work correctly. However, I'm using Desktop.setDefaultMenuBar() to define a menu that appears even when no other windows are open.

import java.awt.Desktop;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Scratch {
    static class MainMenu extends JMenuBar implements ActionListener {

        public MainMenu() {
            JMenu fileMenu = new JMenu("File");
            fileMenu.setMnemonic(KeyEvent.VK_F);

            int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx();

            JMenuItem item = new JMenuItem("New");
            item.setMnemonic(KeyEvent.VK_N);
            item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, keyMask));
            item.addActionListener(this);
            fileMenu.add(item);

            this.add(fileMenu);
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            System.err.println("actionPerformed " + e);
        }
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("Hello Stackoverflow!");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel("Hello Stackoverflow!");
        frame.getContentPane().add(label);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Desktop.getDesktop().setDefaultMenuBar(new MainMenu());
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

The call to Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() is based on this blog entry.

Can anyone see what I'm doing wrong?

I'm testing with Amazon coretto 11 if it matters.

Kenster
  • 23,465
  • 21
  • 80
  • 106
  • You should really first test whether your JDK supports setting the default menu bar. Refer to class `Desktop` instance methods like `isSupported(Desktop.Action.APP_MENU_BAR)` – Abra Oct 08 '19 at 05:02
  • @Abra Thanks for your response. Coretto `Desktop.getDesktop().isSupported(Desktop.Action.APP_MENU_BAR)` returns true on Macos. And the menu does appear and work aside from the accelerator keys. The code that I posted is a sample program which doesn't do everything a real program would. – Kenster Oct 09 '19 at 20:41
  • I noticed the same problem, my solution was stop using this method and use `System.setProperty("apple.laf.useScreenMenuBar", "true");` – Anthony Jan 24 '23 at 13:11

0 Answers0