应用程序范围的键盘快捷键-Java Swing
我想为JavaSwing应用程序创建一个应用程序范围的键盘快捷键。 在所有组件上循环并在每个组件上添加快捷方式,会产生与焦点相关的副作用,似乎是一种蛮力解决方案应用程序范围的键盘快捷键-Java Swing,java,swing,shortcut,keystroke,Java,Swing,Shortcut,Keystroke,我想为JavaSwing应用程序创建一个应用程序范围的键盘快捷键。 在所有组件上循环并在每个组件上添加快捷方式,会产生与焦点相关的副作用,似乎是一种蛮力解决方案 有人有更干净的解决方案吗?安装自定义KeyEventDispatcher。KeyboardFocusManager类也是实现此功能的好地方 对于每个窗口,当在聚焦窗口中时,使用条件为的JComponent.registerKeyboardAction。或者使用: JComponent.getInputMap(WHEN_IN_FOCUSE
有人有更干净的解决方案吗?安装自定义KeyEventDispatcher。KeyboardFocusManager类也是实现此功能的好地方
对于每个窗口,当在聚焦窗口中时,使用条件为
的JComponent.registerKeyboardAction
。或者使用:
JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command);
JComponent.getActionMap().put(command,action);
如。中所述,当您有菜单时,可以向菜单项添加全局键盘快捷键:
JMenuItem item = new JMenuItem(action);
KeyStroke key = KeyStroke.getKeyStroke(
KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
item.setAccelerator(key);
menu.add(item);
对于想知道(像我一样)如何使用KeyEventDispatcher的人,这里有一个我放在一起的示例。它使用HashMap来存储所有全局操作,因为我不喜欢大的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;
}
});
}
/**包含所有全局操作的映射*/
私有HashMap actionMap=新HashMap();
/**在GUI构造中的某个地方调用它*/
私有无效设置(){
KeyStroke key1=击键.getKeyStroke(KeyEvent.VK\u A,KeyEvent.CTRL\u DOWN\u掩码);
actionMap.put(键1,新抽象动作(“action1”){
@凌驾
已执行的公共无效操作(操作事件e){
System.out.println(“按下Ctrl-A:+e”);
}
});
//添加更多操作。。
KeyboardFocusManager kfm=KeyboardFocusManager.getCurrentKeyboardFocusManager();
addKeyEventDispatcher(新的KeyEventDispatcher(){
@凌驾
公共布尔dispatchKeyEvent(KeyEvent e){
击键击键=击键。getKeyStrokeForEvent(e);
if(actionMap.containsKey(击键)){
最终操作a=actionMap.get(击键);
最终ActionEvent ae=新的ActionEvent(e.getSource(),e.getID(),null);
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
a、 执行的行动(ae);
}
} );
返回true;
}
返回false;
}
});
}
可能没有必要使用SwingUtils.invokeLater(),但最好不要阻止全局事件循环。使用以下代码
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”替换为所需的快捷方式。一个简单的示例:
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;
}
});
+这是我找到的最好、最简单的答案。我将升级此X1000,但JFrame没有getInputMap或getActionMapmethod@Can'tTellJFrame
不是JComponent
。需要在顶级窗口中的组件上调用这些方法。例如,第一个解决方案:window.getRootPane().registerKeyboardAction(save.getActionListeners()[0]、KeyStroke.getKeyStroke(KeyEvent.VK_S、KeyEvent.CTRL_MASK)、JComponent.WHEN_IN_IN_FOCUSED_窗口)
用你的JButton的名字替换save
,用你的JFrame的名字替换window
。这不是最简单的解决方案,但绝对是最优雅、最可靠的解决方案。不,这是过时的api(从石器时代的jdk 1.2或1.3开始被actionMap/inputMap取代)@kleopatra-Hmm。谢谢你的评论。我想知道原因。我没找到!不太明白-原因是什么?为什么registerKeyboardAction()被禁用请参阅javadoc(JComponent.registerKeyboardAction(java.awt.event.ActionListener,java.lang.String,javax.swing.KeyStroke,int)):此方法现在已过时,请结合使用getActionMap()和getInputMap()来实现类似的行为。