2012-03-08 3 views
2

프로그램의 경우, KeyListener를 사용하여 '1'버튼을 눌렀을 때 ArrayList에 무언가를 추가했습니다. 이 목록에있는 객체는 지속적으로 시각화됩니다. KeyListener를 사용하면 버튼을 계속 누르고 있어도 유창했습니다.Java Swing - KeyListener보다 훨씬 느린 ActionListener

나중에 JMenuBar를 GUI에 추가했습니다. ArrayList에 무언가를 추가하면 액셀레이터가 KeyStroke '1'로 설정된 자체 JMenuItem과 전에 KeyListener와 동일한 작업을 수행하는 ActionListener가 있습니다. 그러나 성능이 매우 나쁩니다. '1'키를 계속 누르고 있으면 KeyListener와 비교해 매우 느려집니다.

왜 그렇게 느린가요? 내가 뭔가 잘못하고 있는거야? 더 좋은 방법이 있습니까?

... 
    AL al = new AL(); 
    menu.add(createMenuItem("Add", KeyEvent.VK_1, al)); 
} 

private JMenuItem createMenuItem(String text, int key, ActionListener al){ 
    JMenuItem menuItem = new JMenuItem(text); 
    menuItem.setAccelerator(KeyStroke.getKeyStroke(key, 0)); 
    menuItem.addActionListener(al); 
    return menuItem; 
} 

private class AL implements ActionListener{ 
    public void actionPerformed(ActionEvent e){ 
     int keycode = ((JMenuItem)e.getSource()).getAccelerator().getKeyCode(); 
     bla(keycode); 
    } 
} 
+0

당신의'keyPressed (keycode);'코드는 무엇을해야합니까? –

+0

이 메서드를 전혀 변경하지 않았으므로 KeyListener와 잘 작동합니다. 하지만 귀하의 질문에 대답 해주십시오. (Keycode == KeyEvent.VK_1) 인 경우 ArrayList에 객체를 추가하거나 == KeyEvent.VK_ESCAPE 인 경우 프로그램을 종료합니다. – Morrow

+1

키 리스너를 트리핑하면됩니다. –

답변

5

속도 저하가 메뉴 가속기가 처리되는 방식입니다. 프로필을 작성하면 Java 코드 (WindowsXP)에 핫스팟이 없기 때문에 L & F 또는 OS가 될 수도 있습니다. 해결 방법은 메뉴 액셀러레이터를 사용하는 대신 루트 창에 키 바인딩을 추가하는 것입니다.

눌러 '1'(고속) 버튼 모든 KeyListener를 트리거 눌러 '2'메뉴 가속 (감속) 눌러 '3'버튼 키 바인딩을 트리거를 트리거 (고속) 눌러 '4'에 키 바인딩 트리거 할 루트 패닝 (빠른)

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 

import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.KeyStroke; 

public class TestKeySpeed { 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       final JTextArea area = new JTextArea(20, 40); 
       area.setEditable(false); 

       JButton button = new JButton("Just something that has focus"); 
       button.addKeyListener(new KeyAdapter() { 
        @Override 
        public void keyPressed(KeyEvent e) { 
         if (e.getKeyCode() == KeyEvent.VK_1) { 
          area.append("1"); 
         } 
        } 
       }); 

       AbstractAction action = new AbstractAction("Add") { 
        { 
         putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('2')); 
        } 

        @Override 
        public void actionPerformed(ActionEvent e) { 
         area.append("2"); 
        } 
       }; 
       button.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
         KeyStroke.getKeyStroke('3'), "add3"); 
       button.getActionMap().put("add3", action); 

       JMenu menu = new JMenu("File"); 
       menu.add(action); 
       JMenuBar bar = new JMenuBar(); 
       bar.add(menu); 
       JFrame frame = new JFrame("Test"); 
       frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
         KeyStroke.getKeyStroke('4'), "add4"); 
       frame.getRootPane().getActionMap().put("add4", action); 

       frame.setJMenuBar(bar); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.getContentPane().add(new JScrollPane(area)); 
       frame.getContentPane().add(button, BorderLayout.PAGE_END); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       button.requestFocusInWindow(); 
      } 
     }); 
    } 
} 
+0

와우,이게 내가 바라던 바로 그거야, 너의 대답에 대해 대단히 감사한다. SSCCE는 내가 시도한 것보다 훨씬 낫다.) 메뉴 용 메뉴 액셀러레이터와 JPanel의 KeyBindings를 사용하여 의도 한대로 작동한다. – Morrow

+0

+1 포괄적입니다. Mac OS X에서도 모두 똑같이 빠릅니다. – trashgod

+0

'2'는 Win7에서도 느립니다. 분명 OS 의존적이다. – Morrow

4

다른 용도로 응용 프로그램이 느려지고 있습니다. 이 example은 12 개 이상으로 응답합니다. Key Bindings. 유용한 방법 중 하나는 herehere과 같이 메뉴 항목과 다른 구성 요소가 동일한 actions을 공유하도록하는 것입니다.

부록 : ActionListener을 구현하는 대신 AbstractAction을 확장하여 Action을 구현하면 가속기 키를보다 쉽게 ​​관리 할 수 ​​있습니다.

+0

흠, 내 문제는 몇 가지 키 바인딩으로 인해 응답이 없지만 (완벽하게 작동하는) KeyListener를 JMenuItem 단축키 + ActionListener로 대체하기 때문에 발생합니다. 내일 SSCCE를 게시 할 예정입니다. 도움이되기를 바랍니다. 지금까지 감사드립니다! – Morrow

+0

@Morrow : 혼란을 가져 주어서 죄송합니다. 메뉴는 가속기를 구현하기 위해 내부적으로 키 바인딩을 사용합니다. 귀하의 [sscce] (http://sscce.org/)가 존재할 때 의견을 보내주십시오. – trashgod

+0

죄송합니다. 어제 답장을받지 못했습니다. 해결책을 찾았을지라도. Walter Laan은 이미 좋은 예를 제공했습니다. 어쨌든 고마워! – Morrow