我有一个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() ... });
然而,按键没有消耗,我仍然在文本字段中插入了后面的引号。如何在调用操作后阻止按键传播到文本字段?
答案 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
答案 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");}
});
}
}