アプリケーション全体のキーボード ショートカット - Java Swing
質問
Java Swing アプリケーション用のアプリケーション全体のキーボード ショートカットを作成したいと考えています。すべてのコンポーネントをループしてそれぞれにショートカットを追加すると、フォーカス関連の副作用が発生し、強引な解決策のように思えます。
もっときれいな解決策を持っている人はいますか?
解決
カスタム KeyEventDispatcher をインストールします。KeyboardFocusManager クラスもこの機能に適しています。
他のヒント
ウィンドウごとに、次を使用します。 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);
少し単純化した例:
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」を必要なショートカットに置き換えます。