I'm fairly new to Java, and have exhausted my Google'ing for this problem with selection on a JList component. I have a list of strings that dynamically change when the user clicks various JButtons. My JList selection mode is set to SINGLE_SELECTION, and the ListSelectionModel is registered to a custom ListSelectionChangeHandler that implements ListSelectionListener.
My problem is that every time the JList model's contents get modified (by clicking a JButton), the ListSelectionChangeHandler gets called and a NullPointerException occurs - e.g. The user has an item selected in the list, clicks a button, the list contents change, and the listener gets called. I want the ListSelectionListener to only perform some action when a MouseClick fires the event. How can I prevent my listener from firing when the model data gets modified?
Relevant Code:
this.suggestionsList = new JList();
this.suggestionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
ListSelectionModel model = this.suggestionsList.getSelectionModel();
model.addListSelectionListener(new ListSelectionChangeHandler());
class ListSelectionChangeHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent arg0) {
Object selectedValue = suggestionsList.getSelectedValue();
// Perform action on selectedValue
// Enable/Disable components as needed
}
}
Thanks for the help!
The easiest way, of which I can think, is to make a switcher - boolean variable, that will be checked every time in your listener before it starts to really do something. Then you can start all of you modifications with switching this variable off. In case of multithreading, you may need some synchronization here.
Related
I found similar code to the following on Oracle's website. I stripped some irrelevant stuff regarding layout for space reasons.
private JTextField textField;
public class TextDemo extends JPanel implements ActionListener
{
public TextDemo()
{
textField = new JTextField(5);
//This causes a leaking this in constructor warning...
textField.addActionListener(this);
//code here for layout and to add the textfield to the panel
}
private static int ctr = 0;
#Override
public void actionPerformed(ActionEvent evt)
{
System.out.println(ctr++);
}
}
So I made a print statement to print and increment a counter to check when this actionListener is detecting an action.
I was wondering:
Is the only action that triggers this method the enter button?
In my constructor where I attached this to the action listener of the textField object, what exactly happens?
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.
this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this
textField.addActionListener(this); // registering actionlistener
Capturing the action event
#Override
public void actionPerformed(ActionEvent evt)
{
System.out.println(ctr++); //perform some action on click
}
http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
As suggested by Hovercraft Full Of Eels you can also use annonymous inner class as below
textField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//do something
}
});
AFAIK, yes. The listener is called when enter is pressed while the textfield has the focus.
The current object, being constructed, is added to the list of ActionListeners of the text field, so that when enter is pressed in the text field, the current object's actionPerformed() method is called. It's generally a bad practice to pass an object not being fully constructed to another object, because the other object could call it back directly and the object wouldn't be functional, since not fully constructed yet.
First: Typically one uses a DocumentListener for a JTextField. It tells lots more interesting information about what is going on. It actually ties to the document (a sort of Model) that lies behind the GUI field.
Now:
Q1 - It's hard to figure out which mouse and keyboard actions cause the various events on the Swing screen components. As I remember, may be it for ActionPerformed. But there can be custom code added to a sub-class of a JTextField that causes an action event to fire for anything you want. You DO have to be careful if you do this.
Q2: The Listener object is stored in a list of all the objects that want to know when the text field has that action event occur. When it occurs, the text field calls the actionPerformed() method on all the objects in its listener list.
You might want to do some research on the Observer Pattern. That is the a name often used for bits of code that do this sort of thing. It can be used in many situations. The key is that it loosely couples the listener and the listenee (observer and observed). The object listening only has to tell the object to which it is listening that it want to be notified in certain cases. The object that is being listened-to keeps a list of all the various objects listening and what events they want to be informed of. That's all the connection and with the use of simple interfaces, it can be programmed simply.
Is the only action that triggers this method the enter button?
Yes. For JTextFields an ActionEvent is dispatched by pressing ENTER.
In my constructor where I attached this to the action listener of the textField object, what exactly happens?
You register the ActionListener with the component. When an ActionEvent is triggered it dispatches an ActionEvent where actionPerformed is invoked, passing it the details of the source object in the ActionEvent.
The preferred approach for the implementation of ActionListeners is to use a separate anonymous listener per component or a single concrete Action for shared functionality.
I have a Java program with a model and a GUI. On my Frame (that implements Observer) I have put a jcombobox with a list of registration from my model (that extends Observable).
When I click on a button add registration the list in my model changed. And than I do
setChanged();
notifyObservers();
In my update method I want to make change the values of the jcombobox. I tried with a repaint() or something like that, but my combobox doesn't change. I am sure I go to my update method, but I don't know how I have to change the jcombobox.
Can someone help
Your update() implementation should obtain a reference to the combo's model and either set the selected item or add a new item, as warranted. A PropertyChangeEvent, illustrated here, may be an alternative, as it can include both old and new values.
I am trying to perform an action whenever a selected item on the combobox changes. one particular scenario, when action listener is not notified, is when you reset the model on the combobox. I can subscribe with another PropertyChangedListener and listen when the model changes, and then extract selected item, but I simply do not understand why the selected item changed event is not raise dwhen model changes. visually your selection does change, even if you query the cobox for a selected item, it does change from null to some object... ANy clear olution to this, rather than using two separate listeners?
If the action and item listeners don't fire events when model is reset, you can fire those event by yourself by subclassing JComboBox:
public class MyComboBox extends JComboBox
{
#Override
public void setModel(ComboBoxModel aModel) {
super.setModel(aModel);
fireActionEvent();
}
}
But IMHO it is a bug - you should report that to the official bugzilla.
I have a JList with 5 options in it and when one of the items becomes selected or clicked i want the text area next to it to show a paragraph of text relative to the item clicked. It should do this for each item in the list but I cant seem to find how to do it in the API
How would my program know if an item in the JList was selected so I can work with the data?
Use addListSelectionListener. You can create a subclass (anonymous or not) of ListSelectionListener that does the work you want.
myList.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent ev)
{
// handle ev
}
});
You should register a Listener for events on your JList. When the Swing UI fires one off, this Listener class will get the message and react accordingly.
I have a JComboBox named "jComboBox18" and a JTextArea "jTextArea11". Now I want that whenever a item is selected from the "jComboBox18" combo box its corresponding description is shown in the "jTextArea11" textarea.
I have added the appropriate listener to the JComboBox But the JTextArea is not showing any text. The code that I have written is as follows:
private void jComboBox18ItemStateChanged(java.awt.event.ItemEvent evt) {
Object item = jComboBox18.getSelectedItem();
if(item != null) {
ems.logic.Process selectedProcess = (ems.logic.Process)item;
jTextArea11.setText(selectedProcess.getProcessDescription());
jTextArea11.updateUI();
jTextArea11.revalidate();
jTextArea11.validate();
}
}
=====================EDITED===========================================
The method is being called for sure. I am changing the state of one more combobox
which is also being written in this method and its state changes successfully whenever item is selected from the "jComboBox18"
I think That should work. In fact, you should only need the setText() call. My guess is that you're function isn't getting called for some reason. Put a break point in your code and make sure it's getting called.
In the code shown your method is named as jComboBox18ItemStateChanged. Are you sure this method is being called. The ItemListener for a JComboBox should implement the interface ItemListener which declares that the subclasses should implement the below method.
void itemStateChanged(ItemEvent e);
How are you adding an instance of ItemListener to your JComboBox ?
EDIT:
After reading your edit and comments one another possiblity that I can think of is that:
you have a listener that is triggered when the textarea is updated and probably itis undoing the changes done in JComboBox listener.