Setting focus hot keys in Swing is very easy:
tfldPlantsNeeded = new JTextField( FIELD_LEN_MED );
lblPlantsNeeded = new JLabel( "Plants Needed" );
lblPlantsNeeded.setDisplayedMnemonic( 'p' );
lblPlantsNeeded.setLabelFor( tfldPlantsNeeded );
This will give focus to the tfldPlantsNeeded
JTextField when the user presses ALT+p
. It also highlights/displays the character that will trigger the focus change. (In this case, when ALT
is pressed, the 'P' in "Plants" is underlined.)
This is great ... well, kinda. On a Mac, when the user presses ALT
(which is also Option
on the Mac keyboard) the mnemonic is highlited, but the focus change isn't triggered when p
is pressed too. If, however, the user presses Control + Option + p
, then it works as "expected" and focus is changed. (As an aside, if the user DOES press Option + p
, the currently focused text field will get funny characters inserted.)
I know that I can do this myself by specifying custom keybindings via getInputMap
and getActionMap
, but is there a way to change the application global mnemonic modifier so that we can use the automatic keybindings and trigger character highlighting? (In my case, I would like to use Command
or Meta
as the mnemonic modifer key.)
Apparently this isn't as straightforward as you might think, but there is a way.
First of all, for menus (JMenu
) there is a property which is controlled by the look and feel called Menu.shortcutKeys
which you can set manually. This sets the mnemonic modifier for menus in the specific look and feel. If you want more information about this feel free to ask.
In order to set the mnemonic modifier for everything, you need to override the default toolkit (Toolkit
). First of all, run a main method to find what it is with the following lines
System.out.println(System.getProperty("java.awt.headless"));
System.out.println(System.getProperty("awt.toolkit"));
If the first line is null
of false
(see java.awt.Toolkit getDefaultToolkit()
) then the second line will give you the class name which is used as the default Toolkit for your system. I use Windows and the second line gives the output sun.awt.windows.WToolkit
. Now create a class that overrides getFocusAcceleratorKeyMask
in your default toolkit. For me it looks like this
public class MyToolkit extends WToolkit {
@Override
public int getFocusAcceleratorKeyMask() {
return InputEvent.CTRL_DOWN_MASK;
}
}
Finally, we have to tell the system to use it. In your application, put the line
System.setProperty("awt.toolkit", "packagename.MyToolkit");
where you need to set the correct package path to your class. Make sure this line is placed before starting any GUI related code, preferably in the first lines of main
. This should now set CONTROL
as the global mnemonic modifier (or use META_DOWN_MASK
if that's what you want. Look at java.awt.event.InputEvent
for MASK list.).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With