Pregunta

Me gustaría crear un método abreviado de teclado para toda la aplicación para una aplicación Java Swing.Recorrer todos los componentes y agregar el acceso directo a 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?

¿Fue útil?

Solución

Instale un KeyEventDispatcher personalizado.La clase KeyboardFocusManager también es un buen lugar para esta funcionalidad.

Despachador de eventos clave

Otros consejos

Para cada ventana, utilice JComponent.registerKeyboardAction con una condición de WHEN_IN_FOCUSED_WINDOW.Utilice alternativamente:

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

como se describe en el registrarseDocumentos de la API de KeyboardAction.

Para las personas que se preguntan (como yo) cómo usar KeyEventDispatcher, aquí hay un ejemplo que preparé.Utiliza un HashMap para almacenar todas las acciones globales, porque no me gustan las grandes if (key == ..) then .. else if (key == ..) then .. else if (key ==..) .. construcciones.

/** 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() quizás no sea necesario, pero probablemente sea una buena idea no bloquear el bucle de eventos global.

Cuando tienes un menú, puedes 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);

Un ejemplo un poco 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;
  }

});

Utilice el siguiente 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);

Reemplace "ctrl D" con el acceso directo que desee.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top