views:

533

answers:

4

Our swing application uses the "spacebar" key as a shortcut key. In other words, if you press the spacebar anywhere within the application window, it will perform a certain behaviour. What's more, this same behaviour can also be performed by using a JMenuItem in the window's menu bar.

The normal way to implement this is to simply set "spacebar" as the "ACCELERATOR_KEY" for the corresponding JMenuItem, and just let swing take care of the rest. Unfortunately, we can't do this, because if we set "spacebar" as the ACCELERATOR_KEY, the shortcut fires every time the user hits spacebar, even at bad times, like when the user is typing regular text in a textfield inside the application window.

To get around that problem, we've implemented the spacebar as a window-level pseudo shortcut key WITHOUT properly installing it in the corresponding JMenuItem as an ACCELERATOR-KEY. It's working fine, except of course the JMenuItem does not have any shortcut key "hint" on it. That is, the menu item should say "spacebar" in little grey letters right on the menu item, so that our users can "discover" the shortcut key without reading the user manual.

But the text is missing since it only gets added to the menu item when you install the shortcut as an ACCELERATOR-KEY.

So my question is: How can I modify that shortcut key hint text on our JMenuItem, so that I can add the appropriate "hint" myself? It would be nice if I could do this without having to mess around at the Look-and-Feel level, since our application is multiplatform and uses several different LAFS.

A: 

Taking into consideration your requirement not to touch the L&F code, which is where the accelerator text is laid out...

Looking at the code for JMenuItem, it seems that you could create a subclass of JMenutItem for your "spacebar" item, which would override the setAccelerator method to assign the accelerator keyStroke, but not go through the configuration of the action. This should allow for the UI code to do its job of laying out the menu as you like it, without the pesky action being triggered when your users are actually trying to put spaces between their words (do they really need to do that anyway?).

akf
Hmmm this sounds promising, thank you for the reply.I suppose the only problem with this would be that the JMenuItem itself would stop working properly...i.e. if the user clicked on it with the mouse instead of using the shortcut key, the action would still not be properly attached.There might be a way to work around that in there too, though...this is a good starting point. :)
Xanatos
I think the menu item should work with the mouse in the above 'solution.' It is only the keyStroke accelerator that you are mucking around with.
akf
A: 

I don't know if text components are the only component that causes a problem. If so, then maybe you can just customize the Action to use the KeyboardFocusManager to determine which component currently has focus. If it is a text component then you don't invoke your Action.

camickr
Yes, this is basically what I did, though I customized the JMenuItem instead, because I'm reusing my new JMenuItem in other places.
Xanatos
A: 

Does setting the accelerator interfere with the way you've currently implemented it all? If not you could just set the accelerator to the space bar... I am going to go ahead and assume you can't do that. The other thing you could do is override the getAccelerator() on your JMenuItem, so you don't have to copy most of the code from JMenuItem (not that there is much there).

JMenuItem clickSpace = new JMenuItem("Item With Accelerator Hint -->") {
        @Override
        public KeyStroke getAccelerator()
        {
            return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0);
        }
    }
xbakesx
A: 
Xanatos