keytyped - Acceso directo de teclado de aplicación-Java Swing
keypressed java enter (6)
Me gustaría crear un atajo de teclado de aplicación para una aplicación Java Swing. Alinee todos los componentes y agregue el atajo en cada uno, tiene efectos secundarios relacionados con el enfoque y parece una solución de fuerza bruta.
¿Alguien tiene una solución más limpia?
Cuando tiene un menú, puede agregar atajos de teclado globales a los elementos del menú:
JMenuItem item = new JMenuItem(action);
KeyStroke key = KeyStroke.getKeyStroke(
KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
item.setAccelerator(key);
menu.add(item);
Instale un KeyEventDispatcher personalizado. La clase KeyboardFocusManager también es un buen lugar para esta funcionalidad.
Para las personas que se preguntan (como yo) cómo usar KeyEventDispatcher, he aquí un ejemplo que preparé. Utiliza un HashMap para almacenar todas las acciones globales, porque no me gusta grande if (key == ..) then .. else if (key == ..) then .. else if (key ==..) ..
.constructos.
/** 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;
}
});
}
El uso de SwingUtils.invokeLater () tal vez no sea necesario, pero probablemente sea una buena idea no bloquear el ciclo de evento global.
Un pequeño ejemplo simplificado:
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;
}
});
Use la siguiente pieza de código
ActionListener a=new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
// your code
}
};
getRootPane().registerKeyboardAction(a,KeyStroke.getKeyStroke("ctrl D"),JComponent.WHEN_IN_FOCUSED_WINDOW);
Reemplaza "ctrl D" con el acceso directo que quieras.
Para cada ventana, use JComponent.registerKeyboardAction
con una condición de WHEN_IN_FOCUSED_WINDOW
. Alternativamente use:
JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command);
JComponent.getActionMap().put(command,action);
como se describe en los documentos de la API registerKeyboardAction .