Reputation: 55
I'm getting to grips with Java again and playing with Swing. Currently trying to understand JList.
When selecting items in a JList, I enable a button (the "Remove" button). When there's no selection, the button should be disabled (can't remove an item if it's not selected, the JVM tends to vomit if you don't have an item index).
When adding a list item through a JTextField default action (enter), the button enables but there's no selection in the JList. The code to enable the button doesn't even run. How is this happening? Maybe I'm missing a listener somewhere?
All the listeners are in the main class, but it doesn't seem to be a problem with the others. I can't see the class instantiating twice, so it's not that. Any ideas would be great?
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class GUI extends JFrame implements Runnable, ActionListener, DocumentListener, ListDataListener, ListSelectionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
//declare and instantiate interface components
DefaultListModel<String> lm=new DefaultListModel<String>();
JList<String> jl=new JList<String>(lm);
JTextField jt=new JTextField(50);
JButton b_add=new JButton("Add");
JButton b_del=new JButton("Remove");
@Override
public void run() {
//FROM RUNNABLE INTERFACE
//set GUI (JFrame) attributes
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
setName("List of Lists");
setSize(1280, 500);
setLayout(new FlowLayout());
//set component attributes
jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //single selection list
jt.getDocument().addDocumentListener(this);
//other interface components
JScrollPane sp=new JScrollPane(jl);
JButton b_exit=new JButton("Exit");
//other component attributes
sp.setSize(500, 500);
b_add.setEnabled(false);
b_del.setEnabled(false);
//set component listeners
b_add.addActionListener(this);
b_del.addActionListener(this);
b_exit.addActionListener(this);
jt.setActionCommand("TXT");
jt.addActionListener(this);
lm.addListDataListener(this);
jl.addListSelectionListener(this);
//add GUI components
add(jt);
add(sp);
add(b_add);
add(b_del);
add(b_exit);
//set GUI visible
setVisible(true);
}
//FROM ACTIONLISTENER INTERFACE
@Override
public void actionPerformed(ActionEvent ae) {
//default action on text field (enter key)
if (ae.getActionCommand()=="TXT") {
lm.addElement(jt.getText());
jt.setText(null);
} else {
//actions from buttons
switch (ae.getActionCommand()) {
//add button
case "Add":
lm.addElement(jt.getText());
jt.setText(null);
break;
//remove button
case "Remove":
if (jl.getSelectedIndex()>=0) {
lm.remove(jl.getSelectedIndex());
}
break;
//exit button
case "Exit":
setVisible(false);
dispose();
break;
//just in case
default:
break;
}
}
}
//FROM DOCUMENTEVENTLISTENER INTERFACE
@Override
public void changedUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
@Override
public void insertUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
@Override
public void removeUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
//FROM LISTDATALISTENER INTERFACE
@Override
public void contentsChanged(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
@Override
public void intervalAdded(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
@Override
public void intervalRemoved(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
//FROM LISTSELECTIONLISTENER INTERFACE
@Override
public void valueChanged(ListSelectionEvent ls) {
b_del.setEnabled(jl.getSelectedIndex()>=0);
}
}
What should happen is that the "Remove" button should only enable when an item in the JList is highlighted (selected).
Upvotes: 0
Views: 201
Reputation: 150
Just add b_del.setEnabled(false);
in Add case.
//add button
case "Add":
lm.addElement(jt.getText());
jt.setText(null);
b_del.setEnabled(false);
break;
Also, I recommend using system.exit(0)
instead of dispose ()
. For memory reasons only (Obviously, it depends on your needs :) ).
Upvotes: 0
Reputation: 324088
What should happen is that the "Remove" button should only enable when an item in the JList is highlighted (selected).
Then you have too many listeners in your code.
There is no need for the DocumentListener. It doesn't matter if the data in the text field is changed. When you add the data from the text field to the JList, the selection does not change automatically.
There is no need for the ListDataListener. Again, you don't care if the data changes.
The only listener that is relevant to this requirement is the ListSelectionListener
. This listener will fire an event when the selection changes. Then in the listener code you enable/disable the button based on the selection in the list.
Basic code in the listener might be:
int index = list.getSelectedIndex();
button.setEnabled( index = -1 ? false : true );
Read the section from the Swing tutorial on How to Write a ListSelectionListener for more information and a working example.
Upvotes: 1