user1052335
user1052335

Reputation:

Java menu on Mac grayed out on change focus

I have a JFrame with a JMenuBar that I'm developing and testing on a Mac system. On this JFrame, I have programmed one of the JMenus to be disabled. However, when I change focus from my Java application to some other program on my computer and then come back to this JFrame, strange things are happening. I have observed that all of the menus become disabled. I have also observed that all of the menus become enabled. Can anyone tell me what's going on here?

Here's a piece of code that will reproduce the error (at least it does on my machine):

public class MenuProblemExample {

    public static void main(String[] args) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        JFrame frame = new JFrame();
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.add(new JMenuItem("open"));
        menuBar.add(fileMenu);
        JMenu editMenu = new JMenu("Edit");
        editMenu.add(new JMenuItem("select all"));
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        frame.setJMenuBar(menuBar);
        fileMenu.setEnabled(false);
        frame.setVisible(true);        
    }
}

When I run this, the enabled property isn't stable under the action of switching focus to another window and then back again.

Upvotes: 3

Views: 705

Answers (1)

trashgod
trashgod

Reputation: 205865

Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

By design, Mac applications using the screen menubar disable menus in the background. It is up to your application to enable menus appropriately when your application comes to the foreground, using e.g. a WindowListener.

Addendum: For testing, this revised example adds a toggle button that tracks the state of the File > Open menu item.

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToggleButton;

/**
 * @see http://stackoverflow.com/a/13756527/230513
 */
public class MenuProblemExample {

    public static void main(String[] args) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JMenuBar menuBar = new JMenuBar();
                JMenu fileMenu = new JMenu("File");
                final JMenuItem openItem = new JMenuItem("open");
                openItem.setEnabled(false);
                fileMenu.add(openItem);
                menuBar.add(fileMenu);
                JMenu editMenu = new JMenu("Edit");
                editMenu.add(new JMenuItem("select all"));
                menuBar.add(fileMenu);
                menuBar.add(editMenu);
                frame.setJMenuBar(menuBar);
                frame.add(new JToggleButton(new AbstractAction("Toggle") {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JToggleButton b = (JToggleButton) e.getSource();
                        openItem.setEnabled(b.isSelected());
                    }
                }));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

Upvotes: 3

Related Questions