Scorciatoia di tastiera ampia applicazione – Java Swing

Vorrei creare una scorciatoia da tastiera a livello di applicazione per un’applicazione Java Swing. Fare il ciclo su tutti i componenti e aggiungere il collegamento su ciascuno di essi, ha effetti collaterali correlati alla messa a fuoco e sembra una soluzione di forza bruta.

Qualcuno ha una soluzione più pulita?

Installa un KeyEventDispatcher personalizzato. La class KeyboardFocusManager è anche un buon posto per questa funzionalità.

KeyEventDispatcher

Per ogni finestra, utilizzare JComponent.registerKeyboardAction con una condizione di WHEN_IN_FOCUSED_WINDOW . In alternativa utilizzare:

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

come descritto nei documenti API registerKeyboardAction .

Per le persone che si chiedono (come me) come usare KeyEventDispatcher, ecco un esempio che ho messo insieme. Usa una HashMap per memorizzare tutte le azioni globali, perché non mi piace grande if (key == ..) then .. else if (key == ..) then .. else if (key ==..) .. costrutti.

 /** map containing all global actions */ private HashMap actionMap = new HashMap(); /** 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 actionPerformsd(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.actionPerformsd(ae); } } ); return true; } return false; } }); } 

L’uso di SwingUtils.invokeLater () potrebbe non essere necessario, ma probabilmente è una buona idea non bloccare il ciclo degli eventi globali.

Quando hai un menu, puoi aggiungere scorciatoie da tastiera globali alle voci di menu:

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

Un piccolo esempio semplificato:

 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; } }); 

Usa il seguente pezzo di codice

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

Sostituisci “ctrl D” con la scorciatoia che desideri.