2012-10-16 6 views
3

사용자가 바로 가기를 누르고 해당 하위 메뉴가 "접혀"포함 된 하위 메뉴 (JMenu)에 액셀러레이터를 추가하라는 사용자 요청이 있습니다.JMenu 하위 메뉴에 단축키를 설정하는 방법은 무엇입니까?

나는 (자바 또는 다른 언어로) 이와 비슷한 것을 본 모든 것을 기억하지 않습니다. 우리의 응용 프로그램은 Swing을 사용하여 Java로 작성됩니다. 우리는 액셀러레이터가 잘 작동하는 많은 JMenuItem을 가지고 있지만, JMenu에 액셀러레이터를 추가하려고하면 다음과 같은 예외가 발생합니다.

java.lang.Error : setAccelerator()가 JMenu에 대해 정의되지 않았습니다. 대신 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 비헤이비어를 재현하는 것입니다. 그런 다음 UI가 나머지 작업을 수행합니다.

중요한 것은 속성 변경을 실행하고 가속기에 일관된 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

시원하게도 - 노인 스윙에 아직도 놀라움이 있습니다 :-) – 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 - 유용성 캐치 키 스트로크 (keystroke)가 사용할 수있는 시각적 표시가 없습니다 것입니다 – kleopatra

+0

네 말이 맞아, 이건 내가 생각해 보지 못한 단점이 ... – 1r0n1k

+0

서브 메뉴를 열 때까지 매력처럼 작동한다. 고마워. kleopatra에 따르면 키 바인딩이 사용되는 것을 나타내는 지표는 없습니다. 이 정보를 어떻게 든 추가 할 수 있습니까? 그렇다면 솔루션은 완벽 할 것입니다 :-) –