2008-09-19 9 views
27

Je voudrais créer un raccourci clavier à l'échelle de l'application pour une application Java Swing. Faire une boucle sur tous les composants et ajouter le raccourci sur chacun d'entre eux a des effets secondaires liés au focus et semble être une solution de force brute.Raccourci clavier large application - Java Swing

Quelqu'un a une solution plus propre?

Répondre

20

Installez un KeyEventDispatcher personnalisé. La classe KeyboardFocusManager est également un bon endroit pour cette fonctionnalité.

KeyEventDispatcher

37

Pour chaque fenêtre, utilisez JComponent.registerKeyboardAction avec une condition de WHEN_IN_FOCUSED_WINDOW. En variante, utiliser:

JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command); 
JComponent.getActionMap().put(command,action); 

comme décrit dans registerKeyboardAction API docs.

+0

+1 La meilleure, réponse la plus facile je l'ai trouvé. Je vais upvote ce x1000 –

+3

x1001 serait mieux, de cette façon, il aurait au moins un upvote. – Epaga

+0

@Epaga Ou 999 fois –

6

Lorsque vous avez un menu, vous pouvez ajouter des raccourcis clavier globaux à des éléments de menu:

JMenuItem item = new JMenuItem(action); 
    KeyStroke key = KeyStroke.getKeyStroke(
     KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK); 
    item.setAccelerator(key); 
    menu.add(item); 
13

Pour les gens se demander (comme moi) comment utiliser KeyEventDispatcher, voici un exemple que je mets ensemble. Il utilise un HashMap pour stocker toutes les actions globales, parce que je n'aime pas les grandes constructions if (key == ..) then .. else if (key == ..) then .. else if (key ==..) ...

/** map containing all global actions */ 
private HashMap<KeyStroke, Action> actionMap = new HashMap<KeyStroke, Action>(); 

/** call this somewhere in your GUI construction */ 
private void setup() { 
    KeyStroke key1 = KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK); 
    actionMap.put(key1, new AbstractAction("action1") { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println("Ctrl-A pressed: " + e); 
    } 
    }); 
    // add more actions.. 

    KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
    kfm.addKeyEventDispatcher(new KeyEventDispatcher() { 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent e) { 
     KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e); 
     if (actionMap.containsKey(keyStroke)) { 
     final Action a = actionMap.get(keyStroke); 
     final ActionEvent ae = new ActionEvent(e.getSource(), e.getID(), null); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
      a.actionPerformed(ae); 
      } 
     }); 
     return true; 
     } 
     return false; 
    } 
    }); 
} 

L'utilisation de SwingUtils.invokeLater() est peut-être pas nécessaire, mais il est probablement une bonne idée de ne pas bloquer la boucle d'événement mondial.

+0

Pas la solution la plus simple, mais certainement la plus élégante et la plus fiable. –

-1

Utilisez le morceau de code suivant

ActionListener a=new ActionListener(){ 
    public void actionPerformed(ActionEvent ae) 
    { 
    // your code 
    } 
}; 
getRootPane().registerKeyboardAction(a,KeyStroke.getKeyStroke("ctrl D"),JComponent.WHEN_IN_FOCUSED_WINDOW); 

Remplacer "ctrl D" avec le raccourci que vous voulez.

+0

non, c'est obsolète api (remplacé par actionMap/inputMap depuis jdk 1.2 ou 1.3 - de retour à l'âge de pierre) – kleopatra

+0

@kleopatra Hmm. Merci pour le commentaire. Je veux savoir la raison. Je ne l'ai pas trouvé! – user12458

+0

ne comprends pas tout à fait - raison de quoi? – kleopatra

1

Un petit exemple simplifié:

KeyboardFocusManager keyManager; 

keyManager=KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
keyManager.addKeyEventDispatcher(new KeyEventDispatcher() { 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent e) { 
    if(e.getID()==KeyEvent.KEY_PRESSED && e.getKeyCode()==27){ 
     System.out.println("Esc"); 
     return true; 
    } 
    return false; 
    } 

}); 
Questions connexes