JTextField problem with ActionEvent getModifiers method - java

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.

Related

Remove/disable/override Swing's focus traversal keys

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

Adding keyboard shortcuts in applet

How can I add keyboard shortcuts to a Java applet?
I had an assignment (I am taking Honors Computer Science) to make my name spin in a circle.
I used an infinite loop, and every time I want to end, I have to go to Task Manager and end the program. Can I add a shortcut that quits the applet?
For example, if I press the space bar, it will change to another part of the program.
I looked over "How to Use Key Bindings" at Oracle's website but I could not understand it.
If you are using Swing (if you are creating a JApplet), then yes, Key Bindings are the way to go. What about them confuses you?
By the way, I know that this isn't directly related to your question, but if your applet is a Swing JApplet, I wouldn't use an infinite loop to do the animation, but rather I'd use a Swing Timer. If you use an infinite loop, you must take care to a) do the infinite loop in a background thread, and b) make most Swing calls from within the loop on the Swing event dispatch thread (or EDT) else you risk freezing the main Swing thread. A Swing Timer does all of this for you, and is thus much easier to use.
All that tutorial is saying that you need a KeyStroke, some key Object, and an Action to create a key binding.
To create your KeyStroke, take a look at the static helper methods, they should explain how to get the correct KeyStroke you need.
You can use any old Object as the key (Object key = new Object()).
The last thing you need is to create your Action. I would suggest extending AbstractAction since it already implements many of the methods of Action for you.
To put your key binding together do the following:
JComponent c = ...
KeyStroke keyStroke = ...
Object key = ...
Action a = ...
c.getInputMap().put(keyStroke, key);
c.getActionMap().put(key, a);

Swing: How JDialogs talk back to the JFrame

I'm building my first Swing app and am trying to figure out how my JDialogs - exclusively invoked when the user selects a JMenuItem - can update the components in the main client area of the JFrame which is the parent "window" of the whole app.
This is the design I've come up with, but don't know if its: (1) just plain bad, (2) not the standard (thus best) way, or (3) if I'm totally off-base here. Any suggestions are enormously appreciated.
Basically, the user selects a JMenuItem, which launches a JDialog. The user interacts with the components on the dialog, and then clicks "Done". If everything validates, the JDialog closes, and I want the parent window (a JFrame) to have its state updated (and eventually rippled out into its components).
My design:
Have an AppStateController that is a member of the JFrame subclass (my application). I would then create an AppStateChangeListener and AppStateChange EventObject subclass so that whenever a dialog validates and closes, it fires an AppStateChange event. Since the parent JFrame is the only registered listener to that event, I could define a handler that gets the event passed to it. I would make sure the AppStateChangeEvent had enough metadata to describe all the possible changes.
In theory, I like this approach: it should be clean and free of "spaghetti"-type calls to multiple controls every time a different event fires. However, I fear it may be overkill.
What do best practices dictate here? I'm not really a GUI person!
Java has several ways to implement the observer pattern; several are discussed here.
The mechanism prescribed by EventListenerList is probably the most general, as it would allow you to define your own event and listener types, and it is familiar to Swing programmers. Instead of making the JFrame a listener, let the highest level JComponent do so. Each instance of JComponent has a suitable protected member, listenerList.
Bound Properties are also an excellent choice, as shown here.
If you go with Observable, you'll need to use a delegate.
Addendum: As concrete examples, jfreechart uses the EventListenerList scheme to manage chart, dataset and series events. In contrast, jcalendar uses bean properties to notify listeners of widget selections.

Capturing "Tab" key press by both the focused component and its container

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.

How to trigger Java Swing InputVerifier on enter in JComboBox (actionPerformed)?

I have a Swing JComboBox with an InputVerifier set correctly.
I am using the combo box to set an integer.
If I type "cat" in the field and hit tab, my InputVerifier triggers and resets the value to "0".
If I type "cat" and hit enter, my InputVerifier is never called from actionPerformed. Do I need to explicitly call my InputVerifier from actionPerformed?
What's the best model to validate my JComboBox on tab and enter? It seems like this is something that should be given to me "for free" by the swing model.
The problem is "hit Tab" and "hit Enter" mean two different things in Java Swing. But those two actions mean the same thing to you, me, and the user.
Swing has no single mechanism to detect "when the user is done entering data". Instead, Swing focuses on the mechanics of "is this field losing keyboard focus" and "is the user pressing Enter key while inside a field".
Semantically those two actions mean the same thing from the user's perspective: "I'm done. Here's my input.". But, from what I can tell, Swing fails to offer a way to detect that user intention. I'm as surprised as you by the lack of such a feature, as this seems to be the most basic function of a form in a GUI. What we need, but don't have, is a "dataEntered" event.
There is a workaround…
In a similar context (JTextField instead of JComboBox) the Sun/Oracle Java Tutorial provides the example InputVerificationDemo where a class is created that:
Extends InputVerifier (to handle tabbing/clicking where focus is about to be lost)
Implements ActionListener (to handle pressing Enter key without leaving field)
The good thing about this workaround is that you can locate your handling code all in one place. The downside is that you still have the hassle of:
Creating a separate class.
Instantiating that class.
Passing that instance to both the setInputVerifier and addActionListener methods of your widget (JTextField, etc.).
This is the expected behavior of InputVerifier: the TAB key attempts to change focus, while the ENTER key does not. You can bind the ENTER key to a different action, as described in the tutorial How to Use Key Bindings. Also, consider the informative article Key Bindings, which includes a handy utility application.
When using an editable combo box, focus is on a JTextField which is used as the editor of the combo box. You can add an ActionListener to this text field.
In the ActionListener you could try invoking the transferFocus() method which should be equivalent to tabbing our of the text field. If that doesn't work then tha actionListener should invoke the same editing code as the InputVerifier.

Categories