A Java KeyStroke, KeyEvent, Action, InputMap, and ActionMap example

I don't know if this is the "proper" way to handle having multiple keystrokes for one action, but until I find a better approach I thought I'd share this here.

For my Java text editor application, on Mac OS X I want the user to be able to use any of the following keystrokes to increase the font size by one unit:

  • [Apple][=]
  • [Apple][Shift][=]
  • [Apple][+]

Each of those keystrokes might be interpreted by a user as being equivalent to [Apple][+], so I want to be sure I support all three of them.

To tackle this problem, I've defined these three keystrokes as follows:

// handle [meta][equals], [meta][equals][shift], and [meta][plus]
private KeyStroke largerFontSizeKeystroke1 = KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, Event.META_MASK);
private KeyStroke largerFontSizeKeystroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, Event.META_MASK + Event.SHIFT_MASK);
private KeyStroke largerFontSizeKeystroke3 = KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, Event.META_MASK);

Hopefully you can read that code, and see that each keystroke corresponds to my bulleted items above.

Add KeyStroke objects to ActionMap and InputMap

Next, I add each of these KeyStroke definitions to the InputMap and ActionMap for my text editing area, which is technically a JTextPane like this:

largerFontSizeAction = new LargerFontSizeAction(mainFrameController, this, "Increase Font Size", largerFontSizeKeystroke1.getKeyCode());

// add largerFontSizeKeystroke1
getEditorPane().getInputMap().put(largerFontSizeKeystroke1, "largerFontSizeKeystroke");
getEditorPane().getActionMap().put("largerFontSizeKeystroke", largerFontSizeAction);

// add largerFontSizeKeystroke2
getEditorPane().getInputMap().put(largerFontSizeKeystroke2, "largerFontSizeKeystroke2");
getEditorPane().getActionMap().put("largerFontSizeKeystroke2", largerFontSizeAction);

// add largerFontSizeKeystroke3
getEditorPane().getInputMap().put(largerFontSizeKeystroke3, "largerFontSizeKeystroke3");
getEditorPane().getActionMap().put("largerFontSizeKeystroke3", largerFontSizeAction);

As mentioned, I don't know if there is a better way to handle this particular Java KeyStroke need, but I can confirm that this approach does work.

I suspect that I can cut down on half of those lines by using the same "actionMapKey" for all three keystrokes (see the Java InputMap class), but as I'm writing this I'm just a wee bit tired, so I'll try to come back to this later.

Javadoc links

Before I leave, here are links to the Java classes referenced in this tutorial: