2013-06-11 5 views
1

Я пытался использовать клавиши со стрелками как часть моего приложения. Следуя лучшей практике, я застрял в использовании привязок клавиш. Я полагаю, что клавиши бровей не производят ключевое типизированное событие, поэтому я использовал этот answer.Почему Jtoolbar нарушает мои ключевые слова?

Однако мое приложение имеет ряд компонентов, и я обнаружил, что если у меня есть JToolbar в моем JFrame, метод в предыдущей ссылке больше не работает. Почему это и как я могу использовать JToolbar и использовать привязки клавиш?

Вот SSCCE

public class ArrowTest extends JFrame { 

    public static void main(final String[] args){ 
     final ArrowTest at = new ArrowTest(); 
     at.setSize(100,200); 

     final JPanel jp = new JPanel(); 
     jp.setBackground(Color.BLUE); 
     at.getContentPane().add(jp); 
     final JToolBar toolbar = new JToolBar(); 
     toolbar.add(new JButton()); 
     //at.add(toolbar); 
     at.setVisible(true); 
    } 

    public ArrowTest() { 
     super();  
     this.getContentPane().setLayout(new GridBagLayout());  
     this.getContentPane().setBackground(Color.BLACK);  
     this.setKeyBindings(); 
    } 

    public void setKeyBindings() { 

     final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;  
     final ActionMap actionMap = this.getRootPane().getActionMap(); 
     final InputMap inputMap = this.getRootPane().getInputMap(condition); 

     for (final Direction direction : Direction.values()) { 
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText()); 
      inputMap.put(direction.getKeyStroke(), direction.getText()); 
      actionMap.put(direction.getText(), new MyArrowBinding(direction.getText())); 
     } 

    } 

    enum Direction { 
     UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)), 
     DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)), 
     LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), 
     RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)); 

     Direction(final String text, final KeyStroke keyStroke) { 
      this.text = text; 
      this.keyStroke = keyStroke; 
     } 
     private String text; 
     private KeyStroke keyStroke; 

     public String getText() { 
      return text; 
     } 

     public KeyStroke getKeyStroke() { 
      return keyStroke; 
     } 

     @Override 
     public String toString() { 
      return text; 
     } 
    } 

    private class MyArrowBinding extends AbstractAction { 

     private static final long serialVersionUID = -6904517741228319299L; 

     public MyArrowBinding(final String text) { 
      super(text); 
      putValue(ACTION_COMMAND_KEY, text); 
     } 

     @Override 
     public void actionPerformed(final ActionEvent e) { 
      final String actionCommand = e.getActionCommand(); 
      System.out.println("Key Binding: " + actionCommand); 
     } 
    }  
} 
+0

установить сочетание клавиш для ур кадров, и ваша панель Dont жить в вашем фрейме кажется – nachokk

ответ

4

По умолчанию JToolBar регистрирует действие для нажатий клавиш в вверх/вниз/влево/RIGHT и JToolBar, которые вы добавляете в JFrame, автоматически захватывает фокус, поэтому вы не видите ничего при привязке к корневой панели (панель инструментов ловит события перед вами).

Одним из решений является сделать JToolBar и JButton не фокусируемый и позволить вашему JPanel быть фокусирования (на самом деле вы можете оставить JToolBar и JButton и запросить фокус на панель, но это также означает, что вы должны обрабатывать управление фокуса панели):

import java.awt.Color; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JToolBar; 
import javax.swing.KeyStroke; 

public class ArrowTest extends JFrame { 

    public static void main(final String[] args) { 
     final ArrowTest at = new ArrowTest(); 
     at.setSize(100, 200); 

     final JPanel jp = new JPanel(); 
     jp.setBackground(Color.BLUE); 
     jp.setFocusable(true); 
     at.getContentPane().add(jp); 
     final JToolBar toolbar = new JToolBar(); 
     JButton comp = new JButton(); 
     toolbar.add(comp); 
     at.add(toolbar); 
     at.setVisible(true); 
    } 

    public ArrowTest() { 
     super(); 
     this.getContentPane().setLayout(new GridBagLayout()); 
     this.getContentPane().setBackground(Color.BLACK); 
     this.setKeyBindings(); 
    } 

    public void setKeyBindings() { 
     for (final Direction direction : Direction.values()) { 
      MyArrowBinding binding = new MyArrowBinding(direction.getText()); 
      getRootPane().registerKeyboardAction(binding, direction.getText(), direction.getKeyStroke(), 
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
     } 
    } 

    enum Direction { 
     UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)), DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)), LEFT("Left", 
       KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)); 

     Direction(final String text, final KeyStroke keyStroke) { 
      this.text = text; 
      this.keyStroke = keyStroke; 
     } 

     private String text; 
     private KeyStroke keyStroke; 

     public String getText() { 
      return text; 
     } 

     public KeyStroke getKeyStroke() { 
      return keyStroke; 
     } 

     @Override 
     public String toString() { 
      return text; 
     } 
    } 

    private class MyArrowBinding extends AbstractAction { 

     private static final long serialVersionUID = -6904517741228319299L; 

     public MyArrowBinding(final String text) { 
      super(text); 
      putValue(ACTION_COMMAND_KEY, text); 
     } 

     @Override 
     public void actionPerformed(final ActionEvent e) { 
      final String actionCommand = e.getActionCommand(); 
      System.out.println("Key Binding: " + actionCommand); 
     } 
    } 
} 

я также заменил свои вызовы getActionMap/getInputMap одним вызова javax.swing.JComponent.registerKeyboardAction(ActionListener, String, KeyStroke, int)

+0

Большое спасибо за ответ. Я буду использовать 'javax.swing.JComponent.registerKeyboardAction (ActionListener, String, KeyStroke, int)'. Глядя на ваше решение, мне кажется, что мне нужно будет «setFocusable (false)» на каждом компоненте, который я добавляю на панель инструментов. Я думаю, было бы лучше заменить действие на панели инструментов один раз. –

+0

@ medPhys-pl На самом деле нет. Вы даже можете позволить «JToolbar» быть сфокусированным, но тогда вам также нужно каким-то образом сделать ваш компонент привлекательным и обработать щелчок мышью, чтобы запросить фокус на нем. Ваше решение не идеально, потому что вы убиваете действия по умолчанию JToolBar, и если какой-либо другой компонент (не под JToolBar) захватывает фокус, ваши действия больше не будут работать. –

+0

Я включил больше кода моего решения. Я думаю, что это показывает, что ваш второй пункт на другом компоненте, который захватывает фокус, не будет проблемой. Это было непонятно из моего предыдущего поста. Вы правы, я убиваю действия по умолчанию. Что-то не так с перезаписью действий по умолчанию? –

1

Следуя советам в этой answer я решил проблему с помощью

public void setKeyBindings() { 

    final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;  
    final ActionMap actionMap = this.getRootPane().getActionMap(); 
    final InputMap inputMap = this.getRootPane().getInputMap(condition); 

    for (final Direction direction : Direction.values()) { 
     inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText()); 
     inputMap.put(direction.getKeyStroke(), direction.getText()); 
     actionMap.put(direction.getText(), new MyArrowBinding(direction.getText())); 
    } 

    condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT; 

    actionMap = toolbar.getActionMap(); 
    inputMap = toolbar.getInputMap(condition); 


    for (final Direction direction : Direction.values()) { 
     inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText()); 
     inputMap.put(direction.getKeyStroke(), direction.getText()); 
     actionMap.put(direction.getText(), new MyArrowBinding(direction.getText())); 
    } 


}