Java Swing:消耗关键事件

时间:2014-12-23 19:14:13

标签: java swing

我有一个JFrame(包含各种文本字段和表格等),并希望安装一个热键功能,只要帧打开(有点像菜单加速器快捷方式)就适用。以下内容主要起作用,无论哪个字段或控件具有焦点,都会调用我的操作:

String MY_GLOBAL_ACTION_TRIGGER = "hotKey";
InputMap im = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
KeyStroke ks = KeyStroke.getKeyStroke('`');
im.put(ks, MY_GLOBAL_ACTION_TRIGGER);
ActionMap am = getRootPane().getActionMap();
am.put(MY_ACTION_TRIGGER, new AbstractAction() { public void actionPerformed() ... });

然而,按键没有消耗,我仍然在文本字段中插入了后面的引号。如何在调用操作后阻止按键传播到文本字段?

3 个答案:

答案 0 :(得分:2)

使用KeyboardFocusManager和KeyEventDispatcher

private void myListener implements KeyEventDispatcher {
  public boolean dispatchKeyEvent (KeyEvent ke) {
    if (ke.getKeyChar() == '`') {
      MY_GLOBAL_ACTION.actionPerformed(null);
      return true;
    }
    return false;
  }
}

答案 1 :(得分:2)

文本字段可能优先于键事件通知,这意味着直到文本字段更新后才会通知您的键绑定

一般来说,你真的不想监视文本组件上的击键/事件,因为它没有考虑用户将文本粘贴到字段中的用例

如果您要过滤进入textField的内容,则应使用DocumentFilter

请参阅Implementing a DocumentFilter

答案 2 :(得分:1)

这里有两个问题:

  • 使用KeyStroke参数构造的char似乎并没有真正捕捉到中风。尝试使用KeyStroke(KeyEvent key, int modifiers)
  • 文本字段应该过滤选定的笔划,或者听众应该使用它们。

    尝试类似:

    public class KeyStrokeFrame extends JFrame {
        public static void main(String[] args) {
            new KeyStrokeFrame().setVisible(true);
        }
    
        public KeyStrokeFrame() {
            setSize(200, 200);
            JTextField jtf = new JTextField();
            getContentPane().add(jtf);
            String MY_GLOBAL_ACTION_TRIGGER = "hotKey";
            InputMap im = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_1, 0);
            ((AbstractDocument)jtf.getDocument()).setDocumentFilter(new DocumentFilter() {
                @Override
                public void insertString(FilterBypass fb, int offset,
                        String string, AttributeSet attr)
                        throws BadLocationException {
                    if (string.equals("1")) return;
                    super.insertString(fb, offset, string, attr);
                }
    
                @Override
                public void replace(FilterBypass fb, int offset, int length,
                        String text, AttributeSet attrs)
                        throws BadLocationException {
                    if (text.equals("1")) return;
                    super.replace(fb, offset, length, text, attrs);
                }
            });
            im.put(ks, MY_GLOBAL_ACTION_TRIGGER);
            ActionMap am = getRootPane().getActionMap();
            am.put(MY_GLOBAL_ACTION_TRIGGER, new AbstractAction() { 
                public void actionPerformed(ActionEvent e) {
                    System.out.println("pressed");} 
                }); 
            }
    }