pondělí 21. října 2013

Java Swing: Change Global Action Key

Java Swing Look and Feel defines it's own actions and register them globally on key strokes. It may happen, such a global keystroke is the same you need to use for own action. E.g. you define an action hooked on F8 key in the JPanel. But when the user has focused a JTable inside the JPanel and hit F8, then it still triggers the "focusHeader" action instead your action. One solution is to put your action on every component in the JPanel. Or you can change default keys globally:

private static void reregisterGlobalKeys() {
 // F8 to Ctrl+F8
 reregisterGlobalKey("Table.ancestorInputMap", KeyStroke.getKeyStroke(KeyEvent.VK_F8), KeyStroke.getKeyStroke(KeyEvent.VK_F8, KeyEvent.CTRL_DOWN_MASK));
 reregisterGlobalKey("SplitPane.ancestorInputMap", KeyStroke.getKeyStroke(KeyEvent.VK_F8), KeyStroke.getKeyStroke(KeyEvent.VK_F8, KeyEvent.CTRL_DOWN_MASK));
}

private static void reregisterGlobalKey(String uiManagerKey, KeyStroke oldKeyStroke, KeyStroke newKeyStroke) {
 Object inputMapObj = UIManager.get(uiManagerKey);
 if (inputMapObj == null || !(inputMapObj instanceof InputMap)) {
  System.err.println("reregisterGlobalKey inputMap not found: " + uiManagerKey);
  return;
 }
 InputMap inputMap = (InputMap) inputMapObj;
 String actionCommand = (String) inputMap.get(oldKeyStroke);
 if (actionCommand == null) {
  System.err.println("reregisterGlobalKey actionCommand not found for inputMap: " + uiManagerKey + " keyStroke: " + oldKeyStroke);
  return;
 }
 inputMap.remove(oldKeyStroke);
 if (newKeyStroke != null) {
  inputMap.put(newKeyStroke, actionCommand);
 }
}

Keep in mind that these uiManagerKeys and key strokes are Look and Feel dependend.