3

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

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

在此处输入图像描述

在此处输入图像描述

所以我真正想要的不仅仅是当焦点在 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 部分。但我们会看到;)

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

提前致谢!


新增内容:

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

这是我正在制作的程序: 在此处输入图像描述 第二张图片显示了右侧菜单未停靠的状态。 在此处输入图像描述 显然 JMenuBar 应该仍然可见和可操作,因为没有它,程序的许多功能将被禁用。

在这一点上,我开始认为当对话框(未停靠的菜单)取消停靠并集中在上面时,JMenuBar 不可能保持可见。

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

4

2 回答 2

2

解决这个问题的一个关键,双关语,是让一个键绑定共享一个通用的菜单操作,如下所示。请注意菜单项、对话框的内容和(否则是多余的)按钮如何都可以使用相同的Action实例。一些附加说明:

  • 感谢使用getMenuShortcutKeyMask().

  • Swing GUI 对象应事件调度线程 (EDT)上构建和操作。

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

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

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

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

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

MenuBar 菜单问题

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();
            }
        });
    }
}
于 2012-10-27T14:08:41.237 回答
0

解决了!

使用 JFrame 和 setAlwaysOnTop(true) 可以让我在焦点更改时获得 JMenuBar 的预期效果。

于 2012-11-11T09:53:37.380 回答