Anwendungsweite Tastenkombination - Java Swing

Ich möchte eine anwendungsweite Tastenkombination für eine Java Swing-Anwendung erstellen. Das Durchschleifen aller Komponenten und das Hinzufügen der jeweiligen Verknüpfung hat fokusbezogene Nebenwirkungen und scheint eine Brute-Force-Lösung zu sein.

Hat jemand eine sauberere Lösung?

Antworten auf die Frage(6)

Verwenden Sie den folgenden Code

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

Ersetzen Sie "Strg + D" durch die gewünschte Verknüpfung.

 kleopatra08. Juli 2013, 16:59
Das ist eine Frage für das Swing-Team vor über 10 Jahren :-) Früher gab es einen Artikel (alte Swing-Verbindung?), der keyBindings vorstellte, in dem auch das Warum diskutiert wurde.
 JavaTechnical08. Juli 2013, 16:56
Warum ist registerKeyboardAction () veraltet?
 serg.nechaev23. Sept. 2013, 03:50
Siehe javadoc (JComponent.registerKeyboardAction (java.awt.event.ActionListener, java.lang.String, javax.swing.KeyStroke, int)): Diese Methode ist veraltet. Verwenden Sie eine Kombination aus getActionMap () und getInputMap () für ähnliches Verhalten.
 kleopatra05. Juli 2013, 08:34
nein, das ist veraltet api (ersetzt durch actionMap / inputMap seit jdk 1.2 oder 1.3 - vor langer zeit in der steinzeit)
 JavaTechnical08. Juli 2013, 16:47
@kleopatra Hmm. Danke für den Kommentar. Ich möchte den Grund wissen. Ich habe es nicht gefunden!
 kleopatra08. Juli 2013, 16:52
verstehe nicht ganz - Grund für was?

Verwenden Sie für jedes FensterJComponent.registerKeyboardAction mit einer Bedingung vonWHEN_IN_FOCUSED_WINDOW. Alternativ verwenden Sie:

<code>JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command);
JComponent.getActionMap().put(command,action);
</code>

wie im beschriebenregisterKeyboardAction API-Dokumente.

 Can't Tell30. Juli 2015, 11:49
JFrame verfügt jedoch nicht über eine getInputMap-Methode oder eine getActionMap-Methode
 Tom Hawtin - tackline30. Juli 2015, 12:01
@ Kann nicht sagenJFrame ist keinJComponent. Diese Methoden müssen für Komponenten innerhalb des Fensters der obersten Ebene aufgerufen werden.
 Alba Mendez26. Okt. 2011, 18:05
+1 Die beste und einfachste Antwort, die ich gefunden habe. Ich werde dieses x1000 verbessern
 Epaga17. Apr. 2012, 11:46
x1001 wäre besser, auf diese Weise würde er zumindest eine Gegenstimme bekommen.
 Zezombye01. Mai 2018, 22:42
Für ein Beispiel der ersten Lösung:window.getRootPane().registerKeyboardAction(save.getActionListeners()[0], KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); Ersetzensave mit dem Namen Ihres JButton undwindow mit dem Namen Ihres JFrame.

Ein kleines vereinfachtes Beispiel:

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

});
</code>

die sich fragen (wie ich), wie man KeyEventDispatcher benutzt, ist hier ein Beispiel, das ich zusammengestellt habe. Es verwendet eine HashMap zum Speichern aller globalen Aktionen, da ich keine großen magif (key == ..) then .. else if (key == ..) then .. else if (key ==..) .. Konstrukte.

<code>/** 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;
    }
  });
}
</code>

Die Verwendung von SwingUtils.invokeLater () ist möglicherweise nicht erforderlich, aber es ist wahrscheinlich eine gute Idee, die globale Ereignisschleife nicht zu blockieren.

 Haroldo_OK26. Dez. 2011, 14:22
Nicht die einfachste Lösung, aber definitiv die eleganteste und zuverlässigste.

können Sie Menüelementen globale Tastaturkürzel hinzufügen:

<code>    JMenuItem item = new JMenuItem(action);
    KeyStroke key = KeyStroke.getKeyStroke(
        KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
    item.setAccelerator(key);
    menu.add(item);
</code>
Lösung für das Problem

boardFocusManager-Klasse ist auch ein guter Ort für diese Funktionalität.

KeyEventDispatcher

Ihre Antwort auf die Frage