I'm writing a little program with a GUI. It's the first time that im using a JTable and so far everything worked as I wanted it to. But there's one problem I can't seem to solve: Whenever the JTable is focused, no keyboard shortcuts (for my menu, i.e. "Save" etc.) will be processed. The reason is propably that JTable has a very good keyboard support with many built-in functions (which is pretty cool) and therefore doesn't process the keyboard input. But I still want to be able to use my own keyboard shortcuts for my menus etc. Mnemonics work fine, but accelerators don't work at all.
How can I tell my JTable that it should ignore every keyboard input if the control, alt or a combination of alt, control and shift is pressed?
Someone on another forum told me that I should use the Input- & ActionMap classes, but that doesn't really work. So far im only able to process my keyboard input if ONLY the control key is pressed by manually shifting the keyboard focus from the table to the menubar and shifting it back onto the table after the control key is released. That doesn't work if im pressing shift before control, though. I also have to use: KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,2,false) to get the InputMap to recognize the control key input. As you can see I have to put control as the KeyEvent AND the modifiter. That's the only way that it will work. If I try to add another modifier (i.e. shift, alt), the InputMap will not recognize it. The same goes for shift. It only works if I specifiy shift as the modifier and the KeyEvent. I haven't tried alt yet, but it will propably be the same.
It's a start that I got the control key to work, because if the user first presses the control key and THEN all other shortcut key it works without a problem (for example control, then shift and 'a' for adding a row to the table). But if he presses shift first... well, nothing will happen And my "focus-shifting" is kinda clumsy, because the user sees that the JTable loses the focus and regains focus after control is released (and that only works if control is released as the last button. If control is released before the user releases all other keys the InputMap of my menubar [that I configured by using a boolean variable to process the focus back onto the table after control is released if the focus came from the table] will not recognize the input). So the user always has to press control as the first button and release it last. And thats not really good.
The only solution that I see at the moment is to define ALL my keyboard shortcuts again in the Action- and InputMap of the JTable. But thats a lot of work and it would be really annoying to implement all actions and shortcuts twice (for the menu AND the table).
I would really appreciate it if anyone of you could help me. I'm stuck with this problem for almost a week now and I really can't find any way to solve it effectivly.
Thanks Rob. I tried the putClientProperty() approach, but that doesn't seem to work. SSCCE below (well, about as short as a NetBeans project can be ) - there are Edit menu items 'Col left' and 'Col right' which have accelerators of Ctrl-left and Ctrl-right respectively. But pressing the accelerator keys just changes the selected cell in the table, instead of generating the console output you get if you select the menu items 'manually'.
1. KeyStrokes handle by KeyBindings in the InputMap of the JTable
2. KeyStrokes not handled by the table.
In both cases the KeyStroke is intercepted by the table and not passed to the menu item.
The setAutoStartsEdit tip was for bindings that are not handled directly by the JTable. In this case the KeyStroke is passed to the editor. By setting that property to false the KeyStroke will go to the menuitem.
For KeyStrokes that are directly handled by the JTable you would need to deactivate the KeyStroke by using code like:
You would need to do this for all the KeyStrokes that are defined for the table and for your menu items.
I don't know of any shortcut, although I suppose you could iterate through the InputMap of the table to find all KeyStrokes with a Control/Alt modifier and just set the action name to "none"?
Or to get real fancy you could iterate through the menubar/menu/menu items to create an ArrayList of all accelerator KeyStrokes used by your application. Then you remove those KeyStrokes from the JTable InputMap.
Or the other approach (that I've never tried) is to play with the processKeyBindings(...) method of the JTable. You might be able to add some generic code in there to ignore all Control KeyStrokes.
Appreciate that Rob. Unfortunately I've only just started learning about key handling in Java/Swing (in case you hadn't already guessed) so I'll have to read through it a few times before I get the gist of it.
BTW I did add a bit of code into the SSCCE following the OP's suggestion of passing focus back to the menu bar when a table cell is selected, and that does sort of work. I might pursue this approach for a bit and see how it pans out.
The inserted code, after the putClientProperty() call in AccelFrame(), is:
Right - got something I'm happy with. The passing focus thing didn't really work for me, so instead I'm defining key bindings for the table as well as menu item accelerators. It's a bit of a cheat because the accelerators don't actually get used - they're just a way of displaying the key bindings to the user.
I like it because there's no duplication of action name strings/keys etc. - the action is defined for example:
then the key binding is defined using:
and the menu item is defined using:
Full code - feedback welcome: