提问者:小点点

JavaSwing:消费关键事件


我有一个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个答案

匿名用户

使用KeyboardFocus usManager和KeyEventDispatcher

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

匿名用户

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

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

如果您想过滤进入text Field的内容,您应该使用DocumentFilter

请参阅实现DocumentFilter

匿名用户

这里有两个问题:

尝试类似的东西:

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