2012-10-16 40 views
3

我有一個用戶請求,添加一個加速器到子菜單(JMenu),這將允許用戶按下捷徑,並有相應的子菜單「摺疊」,顯示其包含的菜單項。如何爲JMenu子菜單設置加速器?

我不記得每個人都看過類似的東西(無論是Java或任何其他語言)。我們的應用程序是使用Swing以Java編寫的。我們有許多帶有加速器的JMenuItems,但是當我嘗試向JMenu添加加速器時,我得到以下異常:

java.lang.Error:未爲JMenu定義setAccelerator()。改用setMnemonic()。我試過使用MenuDemo!代碼來進一步試驗這一點。

這是我的嘗試:

//a submenu 
menu.addSeparator(); 
submenu = new JMenu("A submenu"); 
submenu.setMnemonic(KeyEvent.VK_S); 
submenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_MASK)); 

的最後一行是一個由我添加的,這將導致異常。

我試過大量的谷歌搜索,但我可以找到的所有文章都是關於如何將加速器添加到JMenuItem的文章。

看起來JMenu並不支持這個本身。是否有任何解決方法來實現這種行爲?

回答

5

另一種選擇是重寫加速器get/set並重現JMenuItem行爲。然後用戶界面將完成剩下的工作。

重要的是引發屬性更改併爲加速器設置一致的get/set。該解決方案的優點是它還提供了快捷/加速器的可視化指示。

這裏是一個小的演示代碼:

import java.awt.event.KeyEvent; 

import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestMenu { 

    protected void initUI() { 
     JFrame frame = new JFrame(TestMenu.class.getSimpleName()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JMenuBar bar = new JMenuBar(); 
     JMenu topMenu = new JMenu("Top Menu"); 
     JMenu subMenu = new JMenu("Sub menu") { 
      private KeyStroke accelerator; 

      @Override 
      public KeyStroke getAccelerator() { 
       return accelerator; 
      } 

      @Override 
      public void setAccelerator(KeyStroke keyStroke) { 
       KeyStroke oldAccelerator = accelerator; 
       this.accelerator = keyStroke; 
       repaint(); 
       revalidate(); 
       firePropertyChange("accelerator", oldAccelerator, accelerator); 
      } 
     }; 
     subMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.CTRL_MASK)); 
     JMenuItem item1 = new JMenuItem("Item 1"); 
     JMenuItem item2 = new JMenuItem("Item 2"); 
     subMenu.add(item1); 
     subMenu.addSeparator(); 
     subMenu.add(item2); 
     topMenu.add(subMenu); 
     bar.add(topMenu); 
     frame.setJMenuBar(bar); 
     frame.setSize(400, 300); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (InstantiationException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (IllegalAccessException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (UnsupportedLookAndFeelException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       new TestMenu().initUI(); 
      } 
     }); 
    } 

} 
+0

很酷 - 老太太還有驚喜Swing :-) – kleopatra

+0

謝謝,這解決了我的問題。這麼容易,但你必須考慮它:-) –

5

我不認爲這是可能的就像那樣。 但你可以做的是添加一個AbstractAction,它模擬點擊。

submenu.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control U"), "expand"); 
    submenu.getActionMap().put("expand", new AbstractAction("expand") { 
     private static final long serialVersionUID = 1L; 

     @Override 
     public void actionPerformed(ActionEvent evt) { 
      submenu.doClick(); 
     } 
    } 
); 

我希望這也適用於你。

+1

我的第一個猜測是,是行不通的 - 但錯了:-) +1 - 可用性美中不足的是,沒有視覺指示其擊鍵使用 – kleopatra

+0

你是對的,這是一個我沒有想過的缺點...... – 1r0n1k

+0

只要打開子菜單,它就像一個魅力,非常感謝。 正如kleopatra所說,沒有指示器顯示使用哪個鍵綁定。有可能,以某種方式添加此信息?然後,解決方案將是完美的:-) –