Java Swing: How to distinguish events triggered by user? - java

I'd like to update GUI elements (JComboBox, JLabel, etc.) from code which shouldn't trigger change event. Is it possible to find out from java.awt.event.ActionEvent or java.awt.event.ItemEvent if the change was caused by an user or by running code like this?
combo.setSelectedItem("my item")

The answer is: no.
But in some cases you can try to analyze the current InputEvent. To get it, use EventQueue.getCurrentEvent(). For example if user has triggered the change on clicking of another component, you can compare the component of the input event and the component of the action event (OK I know: it's unsafe. But in some cases it can help to avoid incrementing of application complexity).

For a button you can get the event modifiers:
int buttonModifiers = evt.getModifiers();
If the button event was generated with a call to doClick() the modifier is 0, otherwise not.
By the way, you can find out such differences relatively easy by logging / printing using evt.toString()
.

Related

Adding timeout to a user interface program

I'm working on a Java project involving user interface, using the Button class and some action listeners.
I have a few buttons (each with an action listener) and I want to add a timeout to the whole program. That means, if no button was clicked-on in a certain amount of time, a specific action should be performed.
I tried adding it among the basic while loop + isDisposed() function. To my knowledge, this loop checks multiple times whether a button was clicked-on. For some reason, I couldn't get the outcome I wanted.
Is there a way to do so with the classes I mentioned? I also couldn't find any suitable functions in the Button class.
Use a Swing Timer (javax.swing.Timer).
Instanciate it with new Timer(CERTAIN_AMOUNT_OF_TIME, e -> timeoutAction()) (If you have a function timeoutAction), disable repeating with setRepeats(false) and start() it.
When the user clicks a button, call restart() on it.
Also, you’re mentioning the Button class, which is an AWT class. I recommend using Swing’s JButton class instead.
It is highly probable that you are using swing, but since this is not specified, I will give you a general answer, with links to swing examples.
First of all, since all your button clicks will behave in a very similar manner, so you will need a custom ActionListener (example). Your custom action listener should perform the action, but set a timestamp or some kind of date value to the current moment. In parallel, you should have a heartbeat event, which periodically (frequently) runs and compares the current moment with the timestamp set by the last button click. And you can see an example of a periodic task here: How to schedule a periodic task in Java?

Listeners in forms with JComponents

Right now, when I have a form with many JComponents, mainly JTextFields, JTextAreas, JComboboxes, JCheckBoxes and JButtons and want to control their behaviour, for instance the change of focus after a certain key was released, I do the following:
I put all my components in a JComponent[] and cycle through it, adding the appropriate listener. When an event is registered by said listener, I check with "instanceof" what kind of JComponent fired the event and assign the proper reaction.
I use this method for instance to cycle with VK_ENTER through the form, or to "firePropertyChange(..)" after a DocumentListener fires, or to add UndoRedoListeners and so on.
My question : is there a better way to do this and if yes, can you explain to me the benefits ?
but my question refers to the general practice of putting all
JComponents in an array and cycling through them for every listener
and every fired event. It works fine enough, but it feels a bit
"uneconomic",so I wanted to know if it is recommended practice, or if
there is a better way of doing it.
I usually write a custom listener (often as an anonymous class) per type/ instance if I have type/ instance specific behavior so that I can avoid instanceof and other other checks.
You'll want to customise the focus tranfersal system.
Take a look at How to Use the Focus Subsystem, in particular Customizing Focus Traversal

Java: I'd like a JLabel to respond to mouse events only sometimes. Is there a way to hide a mouse listener until wanted?

I see there are methods already built for adding and removing mouse listeners, I suppose I could add them and remove them as needed. I just wasn't sure if there was a better way.
Having my JLabel respond to all mouse events over it but sometimes do nothing isn't quite what I'm looking for, it would be nice if my Labels had the mouse listener only when I needed it to. Maybe this whole idea is just a weird approach.
You register the Listener once and for all; you don't turn it off and on.
You can code logic inside to only take action under certain conditions of your choosing. As long as you make the information available that's needed for a decision your implementation should be fine.

Stop receiving all ActionEvents/Stop Listening in Java for a period of time?

I have a simple program that utilizes Java Swing Timer to display an image for 400 miliseconds, in this period of time I just want to stop all ActionListeners or stop taking ActionEvents. I've got 40+ buttons and want a simple way to do this.
Is there anyway to do that in Java?
Can you determine that you are in this "image displayed" state? The image goes up and you set the state to "image displayed" or whatever. Go through your widgets and decide which ones are supposed to be dead while the image is up. Turn them into Observers of this state value. When the state changes, they either enable or disable, as appropriate. The image code doesn't do anything directly to any widget. It just declares that the state is now "image displayed". It's up to the Observers to decide what to do, if anything, with that information.
Or use the GlassPane. That works too. Of course, the GlassPane shuts down everything. If you need to be more selective, you need a more fine-tuned approach.
You can use a temporary GlassPane instance to consume all events by registering empty listeners to it.
Use an undecorated modal JDialog to display the image. Before you make the dialog visible you would start a Timer. When the Timer fires in 400 ms you close the dialog.
I've had similar issues and typically found that its a design issue that got me in that situation. Being the case, I still had to find away around it. To fix the issue, I kept a list of the elements that I wanted to disable (stop listening) and iterated through them at the beginning and end of the timer. For buttons it should be as simple as:
for(Component c : listOfToggledComponents){
c.setEnabled(shouldItBeEnabled);
}
For buttons, this will grey out the button. Similar things happen to other swing components.

java - deactivate a listener

I have a general question regarding listeners.
Lets say I have two JTabbedPanes and both have a ChangeListener. They are both displayed and I want them both to show the same pane (index) so when a user changes the selected pane in one the other changes too.
In brief, one JTabbedPane listener changes the other JTabbedPane using setSelectedTab().
Obviously, the first listener will activate the second listener and the second will reactivate the first in an endless operation.
This will be solved with booleans.
Is there a smarter way to do it?
Is there a way to change a tab without triggering the Listener?
Is there a way to activate the listener only when a user changes it and not the code?
Thank you.
BTW: I always have the same questions with buttons. But with buttons I take the code from the listener and put it in a method. when One button needs to activate a button it calls its code. But in JTabbedPane it is different.
The simple solution is to act only when necessary. For example:
if(currentTab != desiredTab) {
// change tab
}
That will prevent an infinite loop.
If you need to be able to switch the behavior on and off, then using a boolean flag isn't a bad way to go about it. The alternative is the remove the listener, using removeChangeListener. The flag may be more performant as it may avoid memory allocation and deallocation, but a lot depends on the other details of your situation.
share the selectionModel, like
secondTabbedPane.setModel(otherTabbedPane.getModel());

Categories