I am starting to write some code in Java Swing and I am getting a little bit mixed up in the hierarchy of listeners that swing offers. Namely I wanted to know when to use, for instance, an ActionListener over ListSelectionListener and how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
Thanks very much for your responses.
About ActionListener
An action event occurs, whenever an action is performed by the user.
Examples: When the user clicks a button, chooses a menu item, presses
Enter in a text field. The result is that an actionPerformed message
is sent to all action listeners that are registered on the relevant
component. reference
About ListSelectionListener
List selection events occur when the selection in a list or table is
either changing or has just changed. List selection events are fired
from an object that implements the ListSelectionModel interface. To
get a table's list selection model object, you can use either
getSelectionModel method or getColumnModel().getSelectionModel(). reference
Q. how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
The above details and the references contains much information to get start with.
ActionListener is used e.g. for JButton, it tells just that the GUI-element has done something (a button can not do anything except be clicked).
ListSelectionListener contains more information (which element has been choosen).
For more information on when to use which Listener check the javadoc of the element you want to use.
Related
In SWT, I can find plenty of events that fire when text is typed into the combo, the user makes a selection, etc.
Are there any triggers for when the combo list gets updated, though?
E.g., if I the list is
['apple', 'banana']
and it becomes
['apple', 'banana', 'shoe']
is there any trigger for that, and if not, can I create one?
SWT does not send an event if the list of items of a Combo or CComb changes.
If you use a JFace ComboViewer, its IContentProvider gets informed when the viewer's input changes through its inputChanged() method.
If that's not what you want, then you are free to write application code that notifies interested observers about content changes.
I have a JComboBox whose values are retrieved across the net.
I'm looking for a way to indicate that fact to the user, when the user wants to see the list, expands the drop down, and only then the data is being retrieved.
The basic requirements include:
JComboBox's drop-down shouldn't lock the EDT, but the combo's action should not work until there are values.
User should know when all data has been retrieved.
The size (UI real-estate) of the indication should be as small as possible.
Note that the data isn't retrieved until the user wants to see the combo's values (i.e. expands the drop-down list).
The solution i've used:
I've used a SwingWorker to keep the UI responsive. The combo box was overlayed using JIDE's Overlayable with JIDE's InfiniteProgressPanel that listens to the worker.
To avoid locking the EDT, your data retrieval should be done in a background thread. I would use a SwingWorker to find and load the values since this makes available a background thread with other goodies that make it very Swing-friendly. I would make the JComboBox enabled property false until all values have been loaded, and then enable it via setEnabled(true). You will know the SwingWorker is done either through its done() method (by overriding it), or by adding a PropertyChangeListener to the SwingWorker and being notified when its state is SwingWorker.StateValue.DONE.
One way for the user to know that the process is complete is that they will see when the combo box has been re-enabled. If you want a more obvious indicator, you could display a JProgressBar or a ProgressMonitor. This could be displayed in a dialog if you wish to leave the GUI appearance mostly unchanged.
I implemented it by adding "Loading..." item and a special border around the JComboBox. On click separate thread is started adding new items via SwingUtilities.invokeAndWait. When loading is completed the "Loading..." last item is removed.
to not force my users to wait until the data is loaded, combine the answers by eel and stan :-)
start off with the model containing zero or one real value plus the dummy entry "loading"
register a PopupMenuListener and start a SwingWorker loading the data (into a separate datastructure, might be a new model) in its very first menuWillBecomeVisible
while loading, select the dummy entry (and/or whatever else is appropriate to inform the user what's happening), the action has to be aware of "nothing-to-do-yet" as well
listen to the worker, when receiving the DONE replace/fill the data into the combo's model
I have a JTree, a JTable and a JList which displays the same set of objects, but in different order and with different information. If an item is selected from one of the Component, I want to select the same object on the other two Components (meaning they should be highlighted). Naturally I monitor the selection events with a Listener. Here is the problem, when a Component retrieves the selected object, I'll have to make sure the object is selected on the other Components by calling selection methods on them. This, will then notify the selection listeners on the other two components. But each of those events will in turn call selection events on components other than itself, causing an infinite loop going among the three Components.
I see one solution is to use a boolean flag, and make the listeners not propagate the selection if the flag is set. However, this seems cumbersome and not elegant. Is there a way to simply tell JTree, JTable and JList to make the selection but not fire any events (as oppose to fire an event and then catching and stopping it with a boolean flag)?
Take a look at SharedModelDemo. I think it does what you're looking for.
I would use a flag indicating whether it's user changes or internal changes but yu can also remove listeners before selection call and add them after to prevent events firing.
Can anyone point me in the right direct to this? I want the actionlistener in a applet to display 1 of 3 parameters in a jlabel retreived from the html file, When the appropriate option is selected from a combo box.
Cheers
For a combo box you want to add an ItemListener to your combo box to handle the change. You should create some sort of controller class (just a regular class which implements ItemListener) and add this as your listener. Then, in the itemStateChanged method, you program your logic. You probably want to give the ItemListener you create a reference to your panel so that it can make the appropriate changes.
One other note. If you're reading the HTML file on the fly when the drop down is selected, the user interface will freeze up until this operation is complete. This is because these events are fired and executed on the Event Dispatch Thread, the main thread for user interaction. To avoid this, you can either parse the HTML file ahead of time into memory or you can spawn a separate thread in the itemStateChanged event to parse the HTML file. Just remember, when you're done, to use SwingUtilities.invokeLater to get another runnable back on the Event Dispatch Thread to update the drop down. All updates to the Swing user interface must be done from within the Event Dispatch Thread.
I have a JFrame and when the user presses a button is displayed an input jdialog. I need the jdialog to be in non-modal mode and once the user presses ok,
I want to do some action based on the input. Right now I pass my view as reference in the jdialog, so that when the user presses ok, the jdialog calls a method
of the view. Is there a more standardized way to handle this or this is the only way?
I need the jdialog to be in NON-modal mode
Thanks
You can pass a java.lang.Runnable to be called from the JDialog when the user presses the ok button. In this way you can put the code you want to run inside the Runnable itself.
Your current approach using a callback is straightforward, but the observer pattern is commonly used to decrease the resulting tight coupling. Two implementations are typical in Swing:
Arrange for your view to implement the Observer interface and have your input window delegate to a contained instance of Observable. The notifyObservers() method may be used to pass an object reference to the Observer. A very simple example may be found here.
Have your input window maintain an EventListenerList using a custom event in which the view registers interest. Data of interest to the listener can be passed in the event itself. It may be convenient to reuse an existing javax.swing.event or model the custom event on such a type. Every JComponent contains an EventListenerList.