我有一个带有JMenuBar的JFrame,我正在Mac系统上开发和测试它。 在这个JFrame上,我已经将其中一个JMenus编程为禁用。 但是,当我将焦点从我的 Java 应用程序转移到计算机上的其他程序,然后回到这个 JFrame 时,奇怪的事情发生了。 我观察到所有菜单都被禁用了。 我还观察到所有菜单都已启用。 谁能告诉我这里发生了什么?
这是一段将重现错误的代码(至少在我的机器上是这样):
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);
}
}
当我运行它时,启用的属性在将焦点切换到另一个窗口然后再次返回的操作下不稳定。
Swing GUI 对象应仅在事件调度线程上构造和操作。
根据设计,使用屏幕菜单栏的 Mac 应用程序会在后台禁用菜单。当您的应用程序出现在前台时,由您的应用程序适当地启用菜单,例如使用 WindowListener
。
附录:为了进行测试,此修订后的示例添加了一个切换按钮,用于跟踪File > Open
菜单项的状态。
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);
}
});
}
}