Java JDialog 弄乱了 mac 上的 JMenuBar

标签 java macos swing jdialog jmenubar

我有一些关于 JMenuBar 的问题,我似乎无法弄清楚。

我将从问题的缩写开始:该程序由一个 JFrame、一个 JDialog 和一个 JMenuBar 组成。最初,您将看到一个顶部带有 JMenuBar 的 JFrame。但在某些时候,JDialog 会弹出,用户可以在其中填写一些文本字段。我遇到的问题是,一旦焦点转到 JDialog,JMenuBar 就会消失。我想要的是 JMenuBar 始终位于屏幕顶部,除非整个程序不在焦点中。这里有 2 个屏幕截图,在第一个屏幕截图中,选择了 JFrame,在另一个屏幕截图中,选择了 JDialog。

enter image description here

enter image description here

所以我真正想要的不是当焦点在 JFrame 上时只看到 JMenuBar,我想一直看到 JMenuBar。由于 JDialogs 不能像 JFrame 那样在顶部有 JMenuBar,因此我决定不使用多个 JMenuBar,而只使用应该始终可见的那个。

最后,我将给出尽可能小的(并且仍然有效)并且还包含问题的部分代码:

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;

/**
 * @author Guus Leijsten
 * @created Oct 27, 2012
 */
public class MenuBarProblem extends JFrame {
    public MenuBarProblem() {
        super("Frame");
        this.setMinimumSize(new Dimension(270, 200));
        this.setPreferredSize(new Dimension(800, 530));
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JRootPane root = this.getRootPane();
    //Menu
        JMenu fileMenu = new JMenu("File");
        JMenuItem file_exit = new JMenuItem("Exit");
        file_exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
        file_exit.setToolTipText("Exit application");
        file_exit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        fileMenu.add(file_exit);

        JMenuBar menu = new JMenuBar();
        menu.add(fileMenu);
        root.setJMenuBar(menu);

        this.setVisible(true);

        JDialog d = new JDialog(this, "Dialog");
        d.setSize(200, 100);
        d.setLocation(0, (int)root.getContentPane().getLocationOnScreen().getY());
        d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        d.setVisible(true);
    }

    public static void main(String[] args) {
        String os = System.getProperty("os.name").toLowerCase();
        if(os.indexOf("mac") >= 0) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
        }
        new MenuBarProblem();
    }
}

老实说,我认为问题出在 JRootPane 部分。但我们会看到 ;)

有没有其他人遇到过这个问题并设法解决了它,或者有没有人想试一试?

提前致谢!


新增内容:

在下面的示例中,我将展示一个为游戏提供一些功能的版本。

这是我正在制作的程序: enter image description here 第二张图片显示了右侧菜单未停靠的状态。 enter image description here 显然,JMenuBar 应该仍然可见且可操作,因为没有它,程序的许多功能将被禁用。

在这一点上,我开始认为 JMenuBar 不可能在对话框(未停靠菜单)被取消停靠并专注于时保持可见。

我知道 JDialog 上的 JMenuBar 不能采用 mac osx 样式(屏幕顶部),所以是否有任何其他技术可以用于取消停靠,这确实给我一个 mac osx 样式的 JMenuBar?

最佳答案

解决这个问题的一个关键,双关语,是让 key binding分享一个共同点 menu action , 如下所示。请注意菜单项、对话框的内容和(否则是多余的)按钮如何全部使用相同的 Action 实例。一些附加说明:

  • 感谢使用 getMenuShortcutKeyMask()

  • Swing GUI 对象应该event dispatch thread (EDT) 上构造和操作.

  • 应在启动 EDT 之前设置系统属性。

  • 其几何形状已知后,使对话框的 setLocation() 相对于框架。

  • 一个常见的 Mac 习语使用以下谓词:

    if (System.getProperty("os.name").startsWith("Mac OS X") {…}
    
  • 另请参阅此 example .

  • 对于对话框本身的本地使用,还可以考虑 JToolBar .

MenuBarProblem with menu

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

/**
 * @see https://stackoverflow.com/a/13100894/230513
 */
public class MenuBarProblem extends JFrame {

    private static final int MASK =
        Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
    private static final String exitName = "Exit";
    private static final KeyStroke exitKey =
        KeyStroke.getKeyStroke(KeyEvent.VK_W, MASK);
    private final ExitAction exitAction = new ExitAction(exitName);

    public MenuBarProblem() {
        super("Frame");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu fileMenu = new JMenu("File");
        JMenuItem fileExit = new JMenuItem(exitAction);
        fileMenu.add(fileExit);
        JMenuBar menu = new JMenuBar();
        menu.add(fileMenu);

        JDialog d = new JDialog(this, "Dialog");
        JPanel p = new JPanel();
        p.getInputMap().put(exitKey, exitName);
        p.getActionMap().put(exitName, exitAction);
        p.add(new JButton(exitAction));
        d.add(p);
        d.pack();
        d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

        this.setJMenuBar(menu);
        this.pack();
        this.setSize(new Dimension(320, 240));
        this.setLocationByPlatform(true);
        this.setVisible(true);
        d.setLocation(this.getRootPane().getContentPane().getLocationOnScreen());
        d.setVisible(true);
    }

    private static class ExitAction extends AbstractAction {


        public ExitAction(String name) {
            super(name);
            this.putValue(Action.MNEMONIC_KEY, exitKey.getKeyCode());
            this.putValue(Action.ACCELERATOR_KEY, exitKey);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

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

            @Override
            public void run() {
                new MenuBarProblem();
            }
        });
    }
}

关于Java JDialog 弄乱了 mac 上的 JMenuBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13097787/

相关文章:

java - 我可以将引用的 JButton 添加到第二个 JPanel 吗?

java - Java中HashMap和ArrayList的区别?

java - 获取图像 URL 时出现问题

java - 在 Java GUI 中绘制图像

java - 将对象从 Java 传递到 Fitness

java.lang.NoClassDefFoundError : org/hamcrest/SelfDescribing in Intellij

python - 如何卸载 spf13 Vim 发行版?

Python 在 MacOS M1 上导入 MySQLdb 不起作用

c - 操作系统: read raw keyboard input in C

Java组合框 Swing