My action listener on a JComboBox invokes a thread. I would like the component to be disabled until the thread completes.
I have tried calling seEnabled(false) when the thread start and setEnabled(true) when it completes. Unfortunately setEnabled(false) clears the combo box list as well.
Is there a way of disabling the component but retain the original list?
setEnabled(false) definitely doesn't clear the contents of the combo box. Something else must be going on.
Posting your code might help.
Related
I would like to know if there is a way to detect if changes in the selection of a item in a swing JCombobox is done by a user (actively) or is causes by repopulating the Jcombobox.
I have to dynamically repopulate the items of the combobox based on other selection, this also invokes the actionPerformed event
so actionPerformed is invoked by:
selection changed by user
repopulating the jcombobox items.
how to tell the difference?
Thanks of helping !
No, not really.
A possible solution is to disable event notification while the combo box is updated. This can be done in (at least) one of two ways...
Firstly, you could physically remove the listener from the combo box, if you have a reference to it.
Secondly, you set a boolean flag, which when true, the listener would ignore the event.
For example...
I'm working on a program that traverses a list of objects every pass through. When an object's "time" (i.e. number of passes) is up, it brings up a JDialog to request its next task. The problem is how to deal with multiple objects making this request on a single pass.
If I make the JDialog modal, each object makes its request in turn, which is what I want; but the main program window is unavailable, which I do not want.
If the JDialog is not modal, multiple instances appear, one for each pass, which I do not want; or, if I set it up as a singleton, only one instance appears but only the last object int the list to make the request gets to use it.
Is there a way I can pop up the dialog, leave other windows available to the user, and have the other objects wait their turn to use the dialog?
As noted in comments, the problem can be addressed by altering the modality of the parent Window. On the downside, the "behavior is implementation-dependent."
As an alternative, consider traversing the objects in the background thread of a SwingWorker and adding new candidates to a suitable component, e.g. JList, JTable, or JTabbedPane. Selecting an element form the component would bring up a conventional modal dialog, removing the element on completion. A related example is shown here. Each of the suggested components can be labeled with an icon representing its status.
Solved this by setting the original window's ModalExclusionType to "application" and toggling back to "no exclude" once finished.
I have a JTextPane that has a DocumentListener waiting for changes to the underlying HTML document. When the content changes, the event uses JTextPane.scrollToReference to move the view to a certain reference anchor. The problem is that the underlying View in the JTextPane is also listening to the document changes, and doesn't update until after my listener executes, which causes an exception. Is there any way I can force my DocumentListener to execute after any other event listeners for that particular event? Or is there some way I can wait for the view to be updated before executing my code?
First try to use SwingUtilities.invokeLater() for the listener that has to be executed as last. If that doesn't work, build your own priority queue.
Document is model fro JTextComponents, then not good idea put there two or more Listeners wrote changes to the Document,
all event should be done if model invoke all implemented event to the view, then only if are all events done in the view, then is possible moving with JViewport
no idea whats Listener you are implemented, but DocumentListener (e.g.) with FocusListener (e.i.) can creating endless loop with nice exception from RepaintManager
remove Listener that generating exceptions, add Listener if is really required, remove uselles Listeners immediatelly,
Swing quite no guarentee ordering of Listeners, nor events from multiplayed Listeners betweens model_to_view and vice versa
you can testing if Listeners firing events subsequently or gradually by pushing of required event from Swing Action (delayed from Swing Timer) or for asynchronous Listeners (freezed) by Thread.sleep(int)
I wound up having to extend the Viewport and JScrollPane classes to accomplish this. I exposed a listener for the viewport's change event and added my logic in there (which ensured it was the last code executed in the rendering chain).
I have a JPanel with a set of items (for example combo boxes and text fields). Some action listeners are implemented on those items to register user updates.
If the user selects a value in a JComboBox (for example), the action listener captures the event. The corresponding underlying bean method is called and the panel is refreshed. Changing can have an impact on other fields displayed in the pane.
The problem is that when the panel is refreshed, all listeners are triggered, and they call for a refresh themselves. This leads to an infinite loop.
How can I avoid this? I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the panel content.
One option is to have a central boolean value or some indicator that each listener can check to prevent the chaining of events.
Another option is to not refresh the field if the value does not change. That way each component is updated at most once per refresh.
I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the pane content
Then remove the listeners, refresh the pane content and then restore the listeners. This way the listeners only fire when a user change is made.
I think that if your problem is in combobox it just points to a bug. Really, if user changes the value of the combobox, that somehow triggers refresh of the pane the value of the combo box should not be changed second time! So if it is onValueChanged() (or something like this) it should not be called at all when pane is being refreshed.
But if for some reason it happens you can verify whether the old and new values are the same and exit the listener.
If this still does not help I'd suggest you some non-standard solution: try to investigate the stack trace into the listener. Can you identify whether the listener was called as a direct reaction to user's action or after the pane refresh? In this case you can create utility method and put it in the beginning of all relevant listeners.
My applications also suffered from this problem, and solution with the flag, that I should check in every listener and enable/disable in code, feels not very good for me. I always forgot to set this flag to true/false in necessary places.
That is why I decide to implement another solution.
I just subclass all default swing components that I am using often, and implemented custom ValueChanged event that I fire after mouse/keyboard/clipboard/etc events. Now I am always know, that if ValueChanged event is fired, it means, that value was issued by user, not by code. Event handling in this way much more cleaner. This solution solves my problem.
Here is the scenario. I have an swing applet with tons of checkboxes. some of them are disabled/unchecked when checking another. Each ItemStateChange() event executes a method to parse the entire form for changes. Is there a way to tell if an ItemStateChange() event was triggered due to a mouse click or from a setSelected() call?
The ItemStateChange() for each checkbox has the standard parameter java.awt.event.ItemEvent evt
I'd like to only call the processOrder() method once when a box is clicked. Right now it fires for each change thats made, regardless of whether the change happened from setSelected(). Sometimes there are 10+ parseForm(); calls from a single click.
You can't tell whether the source of the event is a mouse click or a setSelected call from the ItemEvent.
It sounds like you have a loop in your check box logic. You might want to add a controller that handles the events and sets each checkbox yet ignores events that occur due to calling setSelected on other check boxes.
Is there a way to tell if an ItemStateChange() event was triggered due to a mouse click or from a setSelected() call?
If your application manually invokes the setSelected() method then you can use code like:
checkBox.removeItemListener(...);
checkBox.setSelected(...);
checkBox.addItemListener(...);
If you are able to change to use a MouseListener instead of an ItemListener and respond to the mouseClicked() event you will only receive the events for the checkbox selected by the user.