我希望为一个Java Swing应用程序创建一个应用程序范围的键盘快捷方式。循环所有组件并在每个组件上添加快捷方式会产生焦点相关的副作用,并且似乎是一种蛮力解决方案。
有没有更清晰的解决方案?
对于每个窗口,使用JComponent.registerKeyboardAction
,设置条件为WHEN_IN_FOCUSED_WINDOW
。另外也可以使用:
JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command);
JComponent.getActionMap().put(command,action);
根据registerKeyboardAction API文档中的描述。对于像我这样想知道如何使用KeyEventDispatcher的人,这是我整理的一个例子。它使用HashMap来存储所有的全局动作,因为我不喜欢大型的if (key ==..) then .. else if (key ==..) then .. else if (key ==..) ..
结构。
/** map containing all global actions */
private HashMap<KeyStroke, Action> actionMap = new HashMap<KeyStroke, Action>();
/** call this somewhere in your GUI construction */
private void setup() {
KeyStroke key1 = KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK);
actionMap.put(key1, new AbstractAction("action1") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Ctrl-A pressed: " + e);
}
});
// add more actions..
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kfm.addKeyEventDispatcher( new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
if ( actionMap.containsKey(keyStroke) ) {
final Action a = actionMap.get(keyStroke);
final ActionEvent ae = new ActionEvent(e.getSource(), e.getID(), null );
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
a.actionPerformed(ae);
}
} );
return true;
}
return false;
}
});
}
使用SwingUtils.invokeLater()可能并非必须,但最好不要阻塞全局事件循环。
JMenuItem item = new JMenuItem(action);
KeyStroke key = KeyStroke.getKeyStroke(
KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
item.setAccelerator(key);
menu.add(item);
import java.awt.KeyboardFocusManager;
import java.awt.KeyEventDispatcher;
import java.awt.event.KeyEvent;
KeyboardFocusManager keyManager;
keyManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
keyManager.addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == 27) {
System.out.println("Esc");
return true;
}
return false;
}
});
ActionListener a=new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
// your code
}
};
getRootPane().registerKeyboardAction(a,KeyStroke.getKeyStroke("ctrl D"),JComponent.WHEN_IN_FOCUSED_WINDOW);
将“ctrl D”替换为您想要的快捷方式。
window.getRootPane().registerKeyboardAction(save.getActionListeners()[0], KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
将save
替换为您的 JButton 的名称,将window
替换为您的 JFrame 的名称。 - Zezombye