Is there a way to propagate a key press from say a JTextField to its container's KeyListener implementation?
So in effect, the keypress would be acted upon by both the text field and the JPanel. Right now the text field is consuming the key press so is nonexistent to the JPanel underneath.
In Swing, the tab key is used to change the focus from one component to another. The article Validating Input discusses InputVerifier, which may help you do what you want.
The question is why do you want to do this? What is your actual requirement as oppose to your attempted solution. Having an event handled by two components is generally not a good idea.
In general you should not use KeyListeners. Swing was designed to use Key Bindings. However, in this case it won't help because as mentioned earlier the focus subsystem handles the tab key.
If this is the only solution to your problem, then I think you can use KeyEventPostProcessor to listen for any KeyEvent. See Global Event Listeners for more info.
Related
I need that all the key events (including Carriage Return, TAB, etc) generated by all child or grandchildren components of a JFrame, to be listened for a single method inside this JFrame. I have googled a lot, but I have not been able to find the solution I need. I found a partial solution using "InputMap/ActionMap", but it only allows to add particular KeyStrokes on the InputMap, but I need all possible Key Strokes to be forwarded to the parent JFrame.
Thanks.
(I saw this thread, but I was expecting a solution within the Swing API, specifically to address this subject.
Check out Global Event Listeners which gives you a couple of choices:
Use an AWTEventListener.
Us a KeyEventPostProcessor.
Note: see the edit (save some time reading)
I'm trying to make my mind-mapping program respond to shortcuts like CTRL+RIGHT (reordering nodes) and TAB (insert child at next indent level). I have a JPanel that handles all of the keystrokes. It resides inside of a JTabbedPane that might be the cause for Key Bindings not working. I've chickened out and decided to just use KeyListener.
The problem is that with the aforementioned key combinations, Swing automatically shifts the focus to some other component. I'd rather not manually put setFocusable(false) everywhere. How can I disable these shortcuts altogether in such a way that the focus will not be shifted, and the relevant KeyEvents will still be sent to my JPanel?
Edit:
I used the following code:
for (int id : new int[] {KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS})
setFocusTraversalKeys(id, Collections.EMPTY_SET);
to disable the default traversal keys (particularly TAB.)
Now the issue is actually why CTRL+UP causes a loss of focus. When pressing CTRL+DOWN, for instance, it's fine. The component behaves as expected. But with CTRL+UP, it works as expected and then focus is shifted/lost somehow. Can anyone say what CTRL+UP means and how to disable it wherever it is? Google isn't helping.
KeyBinding are used for all KeyEvents implemented in Swing APIs, maybe there is/are conflict
is required to override required KeyBindings, change used Keys, set to null, e.i. depends of your requirements
list of KeyBindings by #camickr
Is there a way to find out which component has the actual focus in a Vaadin window!?
No, at least not directly (which is surprising). Please follow the links and discussions indicated in the thread on Vaadin forum.
You can go around it, but it will require certain amount of work. A starting point is the Focusable interface. Basically, you should capture all focus events in all the components.
You can add a focusListener and a blurListener to each component. If a component has focus you set an object to the current component, if blurListener gets called you set it to null.
If the object is != null you just need to check which component it is and you know which one has focus.
When I hit the enter key into a JTextField and I'm pressing one modifier key (like Ctrl or Alt) the ActionEvent is not fired and thus I can't check the modifier key just pressed.
Why is it a bug?
For Swing widgets, key binding should be done through InputMap and ActionMap (although the "obsolete" registerKeyboardAction is simpler). See Keyboard Bindings in Swing in the old Swing Connection, and the JComponent API docs.
The Pluggable Look & Feel rather gets in the way of mapping input events onto actions. Exactly what happens with ActionEvent is up to the current PL&F. Application code directly registering KeyListener generally isn't a good idea in Swing. Some components are made up of other smaller components, meaning InputEvents may or may not get passed on. Input events may get interpreted to perform more than one operation. Generally the whole thing is a mess.
I've a problem with setAccelerator(). Right now, I have the code that works for Ctrl+X for DELETE operation. I want to set the accelerator to Shift+Delete as well for same JMenuItem.
My code as follows:
JMenuItem item = new JMenuItem(menuText);
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_X, KeyEvent.CTRL_MASK));
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_DELETE, KeyEvent.SHIFT_MASK));
but this is working only for Shift+Delete operation. Seems it is overriding the Ctrl+X operation. Can we make both these keystrokes work at the same time?
Please guide.
Yes it can be done. Behind the scenes the setAccelerator() is just creating a Key Binding, however as you noticed the second binding replaces the first.
So, you need to create an Action (not an ActionListener) to add the to the menu item. Read the section from the Swing tutorial on How to Use Actions for more information. Now that you have created the Action, you can share the Action with another KeyStroke by manually creating a Key Binding. You can read the section from the Swing tutorial on How to Use Key Bindings for a detailed explanation. Or you can read my blog on Key Bindings which give some simple code examples.
This second binding will not show up on the menu item itself.
From: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/AWTEvent.html
The masks are also used to specify to which types of events an AWTEventListener should listen.
So you can combine the mask for two keys, but not the KeyEvents.
item.setAccelerator(
KeyStroke.getKeyStroke(
KeyEvent.VK_X, KeyEvent.CTRL_MASK + KeyEvent.SHIFT_MASK));
A workaround solution would be to catch the KeyEvent in the middle (after your component fired it, but before your listeners will act on it) and check, whether its one of the two combinations. Then fire one event, on which you programmatically agree to represent the action you wanted.
The second call indeed overrides the accelerator. If the method starts with set, there will be only one. If the method starts with add, you can have more than one (for example for a number of listeners).
If you want multiple keystrokes to do the same, I think you should add a keyListener to the top frame (or panel, dialog, ...) which invokes the action listeners added to the menuItem.