Java Swing アプリケーション用のアプリケーション全体のキーボード ショートカットを作成したいと考えています。すべてのコンポーネントをループし、それぞれにショートカットを追加すると、フォーカスに関連する副作用があり、ブルート フォース ソリューションのように見えます。
誰もがよりクリーンなソリューションを持っていますか?
各ウィンドウについてJComponent.registerKeyboardAction
、 の条件で使用しますWHEN_IN_FOCUSED_WINDOW
。または、次を使用します。
JComponent.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, command);
JComponent.getActionMap().put(command,action);
registerKeyboardAction API docsで説明されているとおりです。
カスタム KeyEventDispatcher をインストールします。KeyboardFocusManager クラスも、この機能に適しています。
(私のように) 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);
少し単純化した例:
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;
}
});