如何绑定命令 - ?作为帮助菜单的摇摆动作加速器?

时间:2011-11-16 19:08:53

标签: java macos swing keyboard-shortcuts

帮助的标准组合键是mac上的命令 - 。如何将此组合键绑定到菜单项。

注意:由于我们的用户有不同的键盘布局,我正在寻找一种不需要知道什么键“?”的解决方案。位于。

使用KeyStroke.getKeyStroke(String),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_".

我有这个示例代码:

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!");
        }

    }
}

3 个答案:

答案 0 :(得分:6)

在我的键盘上“?”在“/”键上方,所以你也可以使用shift键输入“?”。所以要做你需要使用的绑定:

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

答案 1 :(得分:4)

请参阅KeyEvent API doc - 备注部分:

并非所有字符都有与之关联的键码。例如,问号没有键码,因为没有键盘出现在主层上。

答案 2 :(得分:3)

(令我惊讶的是 - 对我来说:-)不支持对keyIDs“typed”绑定的修饰符:虽然你可以创建并绑定到inputMap中,但是从来没有找到它们,因为内部为类型化keyEvents生成的keyStrokes确实使用了keyChar和忽略修饰符。该创建发生在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));
  }

考虑一下,这可能有意义:按下/释放处理物理键,而键入是一个或多个物理键的最终组合“输出”。如果任何给定组合没有有效的keyChar,则不会生成keyTyped事件。

基本问题是swing / awt开发人员众所周知的美国中心主义:他们只计算在美国布局上的物理键;-)没有办法(我知道)在布局中获取其他键 - 不可知论的方式。希望被证明是错误的