2012-05-01 24 views
0

我怎樣才能得到一個Java 7應用程序有在屏幕的頂部(在Mac)的菜單欄,也有正常工作的鍵盤快捷方式?鍵盤VS上的Java 7菜單衝突的Mac OS

我有一個Swing用戶界面的Java應用程序。許多菜單都有鍵盤等同物,這是必不可少的。

很少有這取決於系統,但在Mac OS X應該出現在屏幕的頂部,而不是每個窗口上的菜單欄,所以我設置apple.laf.useScreenMenuBar

能正常工作在Java 6,但Java 7的(出最後一週!)編譯並運行相同的代碼將導致鍵盤快捷鍵兩次開展菜單操作。例如,在所附的代碼,命令⌘ + ö打開兩個文件對話而不是一個。 (其他鍵盤快捷鍵也會動作兩次,但有時您必須移動窗口才能看到它們的確如此)。

如果我沒有設置apple.laf.useScreenMenuBar,鍵盤問題就會消失,這就是我要做的事情到,但我的Mac用戶會不高興。我真的很想在正確的位置使用菜單欄並使用鍵盤快捷鍵。


制:的Mac OS 10.7.3(獅子)一2010年底的MacBook Pro

的Java 7:
Java版本 「1.7.0_04」
的Java(TM) SE運行時環境(建立1.7.0_04-B21)
爪哇熱點(TM)64位服務器VM(構建23.0-B21,混合模式)

JA VA 6:
Java版本 「1.6.0_31」
的Java(TM)SE運行時環境(建立1.6.0_31-b04-415-11M3635)
爪哇熱點(TM)64位服務器VM(生成20.6- b01-415,混合模式)


當我看着:

why apple.laf.useScreenMenuBar should be gotten rid of 的討論 - 我爲這一切,但它似乎並沒有發生。

關於not using mrj.version to detect that you're on a Mac 的討論 - 不直接相關,但聽起來很有希望。

我的連接代碼(148線)的長度,但我的揮杆編碼的道歉是很老套。它應該在沒有任何特殊標誌或設置的情況下從命令行進行編譯和運行。

import javax.swing.*; 
import java.awt.Toolkit; 
import java.awt.*; 
import java.awt.event.*; 

/** 
* Shows that using the single screen-top menu bar on a Mac with Java 7 
* causes keyboard shortcuts to act twice. 
* 
* To see the problem(on a Mac -- running OS X 10.7.3 in my case): 
* 1) compile on either Java 6 or Java 7 
* 2) run on Java 7 
* 3) give the command-O shortcut 
* You will see two file dialogues. 
* 
*  -- J. Clarke, May 2012 
*/ 

public class MenuBug { 

    private static void go(String[] args) { 

     // Comment out the following line to fix the problem; 
     // leave it active to see the problem. 
     // It doesn't help to ... 
     // ... put the line into a static block. 
     // ... put the line right after the setLookAndFeel call. 
     // ... put the line before after the setLookAndFeel call. 
     System.setProperty("apple.laf.useScreenMenuBar", "true"); 

     MainWindow mainWindow = new MainWindow(); 
    } 

    public static void main(final String[] args) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } 
     catch (Exception e) { 
      JOptionPane.showMessageDialog(null, 
        e + " while loading look and feel", 
        "MenuBug error", JOptionPane.ERROR_MESSAGE); 
      System.exit(1); 
     } 

     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       go(args); 
      } 
     }); 
    } 
} 

class MainWindow extends JFrame { 

    MainWindow() { 
     super ("Main Window"); 

     setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 
     addWindowListener (new WindowAdapter() { 
       public void windowClosing(WindowEvent e) { 
        dispose(); 
        System.exit(0); 
       } 
      }); 

     JMenuBar menuBar = createMenuBar(); 
     setJMenuBar(menuBar); 

     pack(); 
     setSize(350,300); 
     setVisible(true); 
    } 

    private JMenuBar createMenuBar() { 
     JMenuBar mBar = new JMenuBar(); 
     JMenu menu = new JMenu("File"); 
     String[] menuItemNames = new String[] {"New", "Open...", "Other"}; 
     for (int i = 0; i < menuItemNames.length; i++) { 
      String miName = menuItemNames[i]; 
      JMenuItem mi = new JMenuItem(miName); 
      mi.setActionCommand(miName); 
      linkMenuItemToAction(mi); 
      menu.add(mi); 
     } 
     mBar.add(menu); 
     return mBar; 
    } 

    /** 
    * Create an Action for menuItem, and make sure the action and the menu 
    * item know about each other; where appropriate, add keyboard equivalents. 
    * @param menuItem The menu item to be linked to an action. 
    */ 
    private void linkMenuItemToAction(JMenuItem menuItem) { 
     final int META_MASK = 
       Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); 
     Action a = null; 

     String miName = menuItem.getActionCommand(); 
     if (miName.equals ("New")) { 
      a = new NewAction(); 
      menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 
        META_MASK)); 
     } 
     else if (miName.equals ("Open...")) { 
      a = new OpenAction(); 
      menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 
        META_MASK)); 
     } 
     else if (miName.equals ("Other")) { 
      a = new OtherAction(); 
      menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 
        META_MASK)); 
     } 

     menuItem.setEnabled(a.isEnabled()); 
     menuItem.addActionListener(a); 
    } 

    private class NewAction extends AbstractAction { 
     public void actionPerformed(ActionEvent e) { 
      new MainWindow(); 
     } 
    } 

    private void makeDialog() { 
     String dialogTitle = "Please choose a file to open"; 
     FileDialog fileDialog = new FileDialog(this, dialogTitle, 
       FileDialog.LOAD); 

     fileDialog.setVisible(true); 
     String fileName = fileDialog.getFile(); 
    } 

    private class OpenAction extends AbstractAction { 
     public void actionPerformed(ActionEvent e) { 
      makeDialog(); 
     } 
    } 

    private class OtherAction extends AbstractAction { 
     public void actionPerformed(ActionEvent e) { 
      JOptionPane.showMessageDialog(null, 
        "an example message", 
        "not really an error", JOptionPane.ERROR_MESSAGE); 
     } 
    } 
} 
+0

(感謝Qwerty Bob的幫助編輯,我真的應該看起來更加努力,並且自己完成了。)我會在其他地方問這個問題,如果出現一個有用的答案,它會在這裏發佈。 –

+0

更新:鍵盤快捷鍵現在可以工作......但它們沒有在菜單中列出!我在嘗試新的7u7發行版時發現了這一點,但這個新的bug似乎已經在[報告](7b6)中了(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7186371)。 我也更新到Mountain Lion(Mac OS X 10.8.1),但對Lion系統的快速檢查似乎表明,「改進」是因爲Java版本,而不是操作系統更改。 –

+0

更新:Java 1.7u10解決了這個問題,包括在菜單中顯示鍵盤快捷鍵。我目前在OS X 10.8.2,但我認爲其他版本的東西也可以。 –

回答

4

我回答我的問題 - 那種。正如對原文的評論所指出的那樣,Java 1.7u10的麻煩消失了。

0

看起來,這個問題仍然存在,但現在它可以用FN + Backspace鍵(刪除)在Mac上覆制與1.7_21。

我使用了與上面剛剛添加的文本字段相同的示例。在文本框選擇文本的一部分,然後按Delete鍵(FN + Backspace鍵)

更改按鍵就能 「刪除」 在linkMenuItemToAction方法

else if (miName.equals ("Other")) 
{ 
a = new OtherAction(); 
menuItem.setAccelerator(KeyStroke.getKeyStroke("DELETE")); 
} 

,並補充一點:

JTextField textField = new JTextField(10); 
textField.setText("Long long long long long long long text"); 
add(textField, BorderLayout.PAGE_START); 

到主窗口的構造。