我有一个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() ... });
但是,没有使用按键,我仍然会在文本字段中插入一个反向引号。一旦我的操作被调用,我如何防止按键被传播到文本字段?
使用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");}
});
}
}