Adding timeout to a user interface program - java

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?

Related

Does the following situation needs synchronization?

I have a thread which enables and disables a button in certain random time, if the button clicked when it is enabled an action performed will be executed which will change the image of the button. I am concerned about the synchronization here. Suppose the button is about to get disable and got clicked, so now both threads will execute one to disable it and other to change the image. How should I synchronize this?
All Java GUI toolkits (be it Swing, Apache Pivot, JavaFX, AWT, SWT, Android...) are single-threaded. This means that all listeners will always fire in the same thread. So:
no, you don't need to perform any kind of synchronization,
yes, you need to take care so that disabling and enabling the button happens in the gui thread (wahetever it's called). The exact code is toolkit-specific.

use of multiple actionlistener for a button

I always use one ActionListenr for a button, but I find that one component can be assigned multiple action listeners. How we can do that and what is use of it
Thanks in advance
c.addActionListener(actionlistener1);
c.addActionListener(actionlistener2);
It is useful if you need to do several actions that are not necessarily correlated. For example, changing the background color of a button vs appending the action in a Logger vs informing the controller that the button have been pressed, etc...
This allows to be modular: each actionListener can handle a very specific task for a group of components. For example, you can write a default actionListener for all your buttons, and a specific one for a group of buttons that have the same behaviour.
Finally, some objects already have listeners when you instantiate them (JButton have a default FocusListener, JScrollPane a default MouseWheelListener, etc). This allow you to add other behaviours to your components, without overriding previous ones.
How we can do that
That's the easy part, create multiple instance of ActionListeners and use addActionListener. One would assume that they are all different...
and what is use of it
That's a harder question. One could assume that you would use multiple listeners when you want to apply newer logic to the process but not extend from the existing functionality...
Let's say you have a login form. You have a "Login" button. You write an ActionListener to gather the required details and validate them.
Later on, you decide that the button should be disabled during that process. Normally, you would add that functionality to the original code, but for what ever reason (it's not your code etc), you can't.
You could create another ActionListener whose sole purpose was to disable the button when it was pressed.
As an example...

Java Swing: How to distinguish events triggered by user?

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()
.

Is it possible to programatically set an Eclipse RCP button as 'checked'?

I want to programatically set an Eclipse plugin action (button) such as this here:
For example, if the user presses it, I do not want it to toggle off under certain conditions.
This code here creates the action (button):
class MyAction extends Action {
public MyAction() {
super(NAME, IAction.AS_CHECK_BOX);
}
...
Thread.sleep(100); wait a little bit incase there is a thread update issue
if (condition)
setChecked(true); // does not work, it does not force the button to appear as depressed. It just keeps toggling.
...
}
For some reason setChecked(true) does not work.
The problem here I believe is the fact you're calling setChecked inside of Action.run(). Since one of the effects of clicking a checkbox is to check it, you're sneakily trying to cancel the action while it's going on. In fact, I bet the framework code sets checked to true after Action.run() returns, so it's stomping on your change.
Action has a way of letting you control this in a more defined way. Rather than implementing .run(), implement .runWithEvent(Event). This function passes in an Event object that you can use to have finer grained control.
In this case, I think you want to set Event.doit to false. From the docs:
Setting this field to false will cancel the operation.
Another option
Depending on how your condition is calculated, you may want to preemptively enable/disable your checkbox when it changes. This way you can also prevent a tooltip or similar to explain why it's disabled.

Can multiple accelerators be defined for a JMenuItem?

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.

Categories