<< JQuery Tip: Recognizing AJAX Requests on the Server | Home | JavaFX Too Late...But Who Cares >>

[Swing] Application Wide Hotkeys

I'm working on a Swing application and I need the ability to have application wide hotkeys. Basically that means no matter what I am currently doing in my app specific keystrokes always do the same thing. For example I am mimicking IDEA's CTRL+N functionallity. When CTRL+N is pressed a dialog opens with a textfield that allows me to type in a search string. As I type a list below the textfield populates with what my app thinks I am looking for.

I found most of the GlobalHotkeyManager code somewhere on the web. I honestly can't remember where right now. If it looks familiar to you then let me know and I'll give props. Also, if anyone has alternative methods that might be a better approach please let me know.

public class GlobalHotkeyManager extends EventQueue { private static final GlobalHotkeyManager instance = new GlobalHotkeyManager(); private final InputMap keyStrokes = new InputMap(); private final ActionMap actions = new ActionMap(); private final static String LOOKUPDIALOG_KEY = "LOOKUP_DIALOG"; private final KeyStroke lookupDialogHotkey = KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK, false); static { // here we register ourselves as a new link in the chain of // responsibility Toolkit.getDefaultToolkit().getSystemEventQueue().push(instance); } private GlobalHotkeyManager() { getInputMap().put(lookupDialogHotkey, LOOKUPDIALOG_KEY); getActionMap().put(LOOKUPDIALOG_KEY, new LookupDialogAction()); } // One is enough - singleton public static GlobalHotkeyManager getInstance() { return instance; } public InputMap getInputMap() { return keyStrokes; } public ActionMap getActionMap() { return actions; } protected void dispatchEvent(AWTEvent event) { if (event instanceof KeyEvent) { // KeyStroke.getKeyStrokeForEvent converts an ordinary KeyEvent // to a keystroke, as stored in the InputMap. Keep in mind that // Numpad keystrokes are different to ordinary keys, i.e. if you // are listening to KeyStroke ks = KeyStroke.getKeyStrokeForEvent((KeyEvent) event); //if (DEBUG) System.out.println("KeyStroke=" + ks); String actionKey = (String) keyStrokes.get(ks); if (actionKey != null) { //if (DEBUG) System.out.println("ActionKey=" + actionKey); Action action = actions.get(actionKey); if (action != null && action.isEnabled()) { // I'm not sure about the parameters action.actionPerformed( new ActionEvent(event.getSource(), event.getID(), actionKey, ((KeyEvent) event).getModifiers())); return; // consume event } } } super.dispatchEvent(event); // let the next in chain handle event } }

I left the relevant comments in the code so that it should be fairly straight forward. GlobalHotkeyManager is a singleton because we only ever want one manager running per application instance. I have an Application class I use that acts as sort of Session object for the application. It has getter and setter methods for global components that I need access to and it saves me from having huge constructors where I might have to pass in 10 different objects just to display a particular screen. The GlobalHotkeyManager is created and then set in my Application class.

Application.getInstance().setHotkeyManager(GlobalHotkeyManager.getInstance());

The LookupDialogAction class is really simple.

public class LookupDialogAction extends AbstractAction { public void actionPerformed(ActionEvent e) { setEnabled(false); new LookupDialog(Application.getInstance().getMainFrame(), true); setEnabled(true); } }

I haven't yet completed the LookupDialog code that actually does the work once the dialog is visible. I'm planning that for another article because I am going to use it to demonstrate a great API I found called GlazedLists.

Tags :


Re: [Swing] Application Wide Hotkeys

Greg, if you intend on building IntelliJ like suggestions I'd recommend you to check out the IntelliHints components from the Jide Common Layer project (http://jide-oss.dev.java.net)

Re: [Swing] Application Wide Hotkeys

Thanks. I've been considering JIDE's Common Layer for a few things. In truth I had forgotten about their IntelliHints. The only thing I don't like about them is that you have to do something extra to see the hints. Although that might be able to be changed. I'll have to take a look at it.

Re: [Swing] Application Wide Hotkeys

Hi Gregg, installing a custom EventQueue is heavy weapon (and might go wrong, as Kirill noted in his blog). So I would suggest to try something less almighty first: a KeyEventDispatcher registered with the current KeyboardFocusManager should do the trick as well. Cheers Jeanette

Re: [Swing] Application Wide Hotkeys

One solution is to simply ensure that each action has a corresponding JMenuItem in one of your menus. Assign accelerators to the menu items, and you get global keyboard handling for free from Swing's built-in menu infrastructure.

Add a comment Send a TrackBack