【问题标题】:Java menu on Mac grayed out on change focusMac 上的 Java 菜单在更改焦点时显示为灰色
【发布时间】:2012-12-07 00:12:41
【问题描述】:

我有一个带有 JMenuBar 的 JFrame,我正在 Mac 系统上进行开发和测试。在这个 JFrame 上,我已将其中一个 JMenu 编程为禁用。但是,当我将焦点从 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);        
    }
}

当我运行它时,在将焦点切换到另一个窗口然后再返回的操作下,启用的属性不稳定。

【问题讨论】:

  • 你能发布一个SSCCE或截图吗?
  • 对我来说一切正常。我不是 Mac OS 用户,但我敢打赌这行代码有问题:System.setProperty("apple.laf.useScreenMenuBar", "true"); 你为什么要设置该属性?
  • 它使框架的菜单栏以 Mac OSX 操作系统中本地应用程序的方式显示在屏幕顶部。
  • UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 代表什么? :)
  • 我不明白你的问题。该代码不在我的示例中。

标签: java macos swing jmenu


【解决方案1】:

Swing GUI 对象应event dispatch thread 上构造和操作。

根据设计,使用屏幕菜单栏的 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);
            }
        });
    }
}

【讨论】:

  • org.jhotdraw.samples.draw.Main,引用here,就是一个例子。
  • 好吧,我当然可以使用 WindowListener,但我很好奇你说这种行为是“设计使然”的。当然,当我的应用程序不在焦点上时,该菜单必须消失,但我看不出我的菜单项的属性应该如何改变只是从将焦点移动到另一个窗口并返回。特别是考虑到我已经看到从突然启用的所有菜单项到突然禁用的所有菜单项的变化不可预测,我认为这是一个错误。
  • 我不能排除错误,但 Apple 的 Human Interface Guidelines 指定管理单个项目的 启用 状态。如果您在 EDT 上工作,您将遇到不可预知的行为。进入 EDT 后,如上所示,继续使用会更容易。
  • 感谢您指出有关在事件调度线程上工作的问题。这是我不知道我不知道的事情之一。
  • @AdamCross:这是基础,但很容易被忽视。我认为您对项目与菜单的看法是正确的。我已经更新了示例以供参考。
猜你喜欢
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 1970-01-01
  • 2020-03-28
  • 2011-06-19
相关资源
最近更新 更多