7 votes

Comment lier command- ? comme accélérateur d'action swing pour un menu d'aide ?

La combinaison de touches standard pour l'aide est command - ? sur les macs. Comment puis-je lier cette combinaison de touches à un élément de menu.

Note : Comme nos utilisateurs ont des claviers différents, je cherche une solution qui ne nécessite pas de savoir sur quelle touche se trouve " ?".

Utilisation de KeyStroke.getKeyStroke(String) ce que dit la javadoc ;

Parses a string and returns a `KeyStroke`. The string must have the following syntax:

<modifiers>* (<typedID> | <pressedReleasedID>)

modifiers := shift | control | ctrl | meta | alt | button1 | button2 | button3
typedID := typed <typedKey>
typedKey := string of length 1 giving Unicode character.
pressedReleasedID := (pressed | released) key
key := KeyEvent key code name, i.e. the name following "VK_".

J'ai cet exemple de code :

import javax.swing.*;
import java.awt.Dimension;
import java.awt.event.ActionEvent;

public class HelpShortcut extends JFrame {

    public HelpShortcut(){
        // A few keystrokes to experiment with
        //KeyStroke keyStroke = KeyStroke.getKeyStroke("pressed A");    // A simple reference - Works
        //KeyStroke keyStroke = KeyStroke.getKeyStroke("typed ?");      // Works
        KeyStroke keyStroke = KeyStroke.getKeyStroke("meta typed ?");   // What we want - Does not work

        // If we provide an invalid keystroke we get a null back - fail fast
        if (keyStroke==null) throw new RuntimeException("Invalid keystroke");

        // Create a simple menuItem linked to our action with the keystroke as accelerator
        JMenuItem helpMenuItem = new JMenuItem(new HelpAction());
        helpMenuItem.setAccelerator(keyStroke);

        // Install the menubar with a help menu
        JMenuBar mainMenu = new JMenuBar();
        JMenu helpMenu = new JMenu("Help");
        helpMenu.add(helpMenuItem);
        mainMenu.add(helpMenu);

        setJMenuBar(mainMenu);
    }

    // Scaffolding
    public static void main(String[] pArgs) {
        HelpShortcut helpShortcut= new HelpShortcut();
        helpShortcut.setLocationRelativeTo(null);
        helpShortcut.setSize(new Dimension(100, 162));
        helpShortcut.setVisible(true);
    }

    private class HelpAction extends AbstractAction {

        public HelpAction() {
            putValue(Action.NAME,"Help me!");

        }

        @Override
        public void actionPerformed(final ActionEvent pActionEvent) {
            JOptionPane.showMessageDialog(HelpShortcut.this,"You should ask StackOverflow!");
        }

    }
}

6voto

camickr Points 137095

Sur mon clavier, le " ?" se trouve au-dessus de la touche "/", ce qui signifie que vous devez également utiliser la touche "shift" pour taper le " ?". Donc pour faire la liaison, vous devez utiliser :

// KeyStroke keyStroke = KeyStroke.getKeyStroke("meta typed ?");
int modifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() 
             + KeyEvent.SHIFT_DOWN_MASK;
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, modifier);

4voto

wzberger Points 658

Voir Documentation API KeyEvent - section des notes :

Tous les caractères ne sont pas associés à un code clé. Par exemple, il n'y a pas de code pour le point d'interrogation car il n'y a pas de clavier pour lequel il apparaît sur la couche primaire.

3voto

kleopatra Points 31585

(étonnamment - pour moi :-) les modificateurs de liaisons de keyIDs "typés" ne sont pas supportés : bien que vous puissiez en créer et les lier dans l'inputMap, ils ne sont jamais trouvés car les keyStrokes générés en interne pour les keyEvents typés utilisent le keyChar et ignorent les modificateurs. Cette création se fait dans JComponent.processKeyBindings(...)

boolean processKeyBindings(KeyEvent e, boolean pressed) {
  if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) {
      return false;
  }
  // Get the KeyStroke
  KeyStroke ks;

  if (e.getID() == KeyEvent.KEY_TYPED) {
      ks = KeyStroke.getKeyStroke(e.getKeyChar());
  }
  else {
  ks = KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
                (pressed ? false:true));
  }

En y réfléchissant, cela peut avoir un sens : pressed/released gère les touches physiques, tandis que typed est la "sortie" combinée finale d'une ou plusieurs touches physiques. S'il n'y a pas de keyChar valide pour une combinaison donnée, aucun événement keyTyped n'est généré.

Le problème de base est le centrisme américain bien connu des développeurs de swing/awt : ils n'ont compté comme touches physiques que celles du layout américain ;-) Il n'y a aucun moyen (à ma connaissance) d'accéder à d'autres touches d'une manière indépendante de la disposition. J'espère qu'on me prouvera le contraire

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X