简体   繁体   English

Java Swing:消耗关键事件

[英]Java Swing: consuming key events

I have a JFrame (containing various text fields and tables etc.) and want to install a hot key function that applies whenever the frame is open (a bit like a menu accelerator shortcut). 我有一个JFrame(包含各种文本字段和表等),并希望安装一个热键功能,适用于帧打开时(有点像菜单加速器快捷方式)。 The following mostly works, and my action is invoked regardless of which field or control has focus: 以下内容主要起作用,无论哪个字段或控件具有焦点,都会调用我的操作:

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() ... });

However, the key press isn't consumed and I still get a back quote inserted into the text field. 但是,按键没有被消耗,我仍然在文本字段中插入了后面的引用。 How can I prevent the key press being propagated to text fields once my action has been invoked? 一旦我的动作被调用,如何防止按键传播到文本字段?

Use the KeyboardFocusManager and a KeyEventDispatcher 使用KeyboardFocusManager和KeyEventDispatcher

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

It is likely the text fields are getting precedence on the key event notification, meaning your key binding isn't getting notified until after the text field has been updated 文本字段可能优先于键事件通知,这意味着在文本字段更新之后才会通知您的键绑定

Generally speaking, you really don't want to monitor key strokes/events on text components, as it does not take into consideration the use case where the user pastes text into field 一般来说,你真的不想监视文本组件上的关键笔划/事件,因为它没有考虑用户将文本粘贴到字段的用例

If you want to filter content going into textField you should use a DocumentFilter 如果要过滤进入textField的内容,则应使用DocumentFilter

See Implementing a DocumentFilter 请参阅实现DocumentFilter

There are two issues here: 这里有两个问题:

  • The KeyStroke constructed with char argument doesn't seem to actually catch the stroke. 使用char参数构造的KeyStroke似乎并没有实际捕获中风。 Try using KeyStroke(KeyEvent key, int modifiers) . 尝试使用KeyStroke(KeyEvent key, int modifiers)
  • The textfields should filter the selected stroke, or rather a listener should consume them. 文本字段应该过滤选定的笔划,或者更确切地说,监听器应该使用它们。

    Try something like: 尝试类似的东西:

     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");} }); } } 
  • 声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM