Reputation:
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
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