usar teclado keytyped keyreleased keypressed eventos evento entre diferencia como java swing shortcut keystroke

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.

KeyEventDispatcher


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 .