2012-10-27 58 views
3

我对JMenuBar有一些问题,我似乎无法弄清楚。Java JDialog在mac上搞砸了JMenuBar

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

enter image description here

enter image description here

所以我真正想要的是不是仅仅看到的JMenuBar当焦点在JFrame的,我希望看到的JMenuBar所有的时间。由于一个JDialogs不能像顶一个JFrame一样拥有JMenuBar,所以我决定不使用多个JMenuBars,而只是一个应该始终可见的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(); 
    } 
} 

如果我可以honoust,我觉得现在的问题在于在JRootPane的一部分。但我们会看到;)

有没有其他人遇到过这个问题,并设法解决它alrady,或有没有人想给它一个镜头?

在此先感谢!


新增内容:

在下面的例子中,我将展示一个版本,提供了一些功能的发挥。

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

在这一点上,我开始认为当对话框(未锁定菜单)被解除锁定并且专注于JMenuBar时,JMenuBar不可能保持可见。我知道JDialog上的JMenuBar不能处于mac osx样式(屏幕顶部),那么是否还有其他技术可以用于取消对象,这确实给了我一个mac osx样式的JMenuBar?

+0

不是osx用户,通过正确使用JMenuBar发生了什么,把它放到JFrame – mKorbel

+0

你是什么意思mKorbel?我将需要比这更多一点。像什么是使用JMenuBar的正确方法?并把什么JFrame? @mKorbel – Triplle

+0

[例如](http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html#create),RootPane(我的观点,纠正我,如果我错了)是本地操作系统和Java图形工具包(AWT) – mKorbel

回答

2

双关语意图解决此问题的一个关键是让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(); 
      } 
     }); 
    } 
} 
+0

电池不包括 – mKorbel

+0

非常有用的信息alrady。感谢这些提示。我会在短时间内完成这些工作。首先必须完成考试;) – Triplle

+0

我遇到了另一个问题...当我复制粘贴上面给出的代码。当关注对话时,我仍然没有菜单栏。奇怪的是,在代码上方的截图中,即使焦点位于对话框上,也有一个菜单栏。因此,任何想法是什么导致这个问题? – Triplle

0

解决了!

通过使用setAlwaysOnTop(true)使用JFrame,可以让焦点更改时获得JMenuBar的效果。