我对JMenuBar有一些问题,我似乎无法弄明白。
我将首先解决问题:该程序由JFrame,JDialog和JMenuBar组成。最初,您将看到顶部带有JMenuBar的JFrame。但在某些时候,JDialog会弹出用户可以填写一些文本字段的位置。我遇到的问题是,一旦焦点转到JDialog,JMenuBar就会消失。我想要的是JMenuBar始终保持在屏幕的顶部,除非整个程序不在焦点。这是2个截图,在第一个屏幕截图中,JFrame被选中,而另一个选择了JDialog。
所以我真正想要的是,当焦点在JFrame上时,我只想看到JMenuBar,而不是只看到JMenuBar。由于JDialogs不能将JMenuBar放在顶部,就像JFrame一样,我决定不再拥有多个JMenuBars,而只是一直应该可见的JMenuBars。
最后,我将给出尽可能小(并且仍在工作)的代码的一部分,并且还包含问题:
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?
答案 0 :(得分:2)
解决这个问题的一个关键,即双关语,是让key binding分享一个共同的menu action,如下所示。请注意菜单项,对话框的内容和(其他多余的)按钮都可以使用相同的Action
实例。一些补充说明:
赞赏使用getMenuShortcutKeyMask()
。
应在event dispatch thread (EDT)上仅构建和操作Swing GUI对象。
系统属性应在开始EDT之前设置。
在的几何图形已知之后,使对话框的setLocation()
相对于框架。
常见的Mac惯用法使用以下谓词:
if (System.getProperty("os.name").startsWith("Mac OS X") {…}
另请参阅此example。
要在对话框本身中进行本地使用,还请考虑JToolBar
。
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();
}
});
}
}
答案 1 :(得分:0)
解决!
使用带有setAlwaysOnTop(true)的JFrame,可以在焦点发生变化时获得JMenuBar所需的效果。