JList Event catching
I need to be able to disable users from selecting items in a JList. I have extended the JList class and added a custom ListSelectionListener which, after a user clicks on an item in the JList to move it, quickly moves it back to its original position.
This happens so quickly, it appears as though the selection never took place in the first place.
The problem I am having is that the ListSelectionEvent object identifies the first and last rows that changed in numerical order, and not in the order in which they went (i.e.instead of the getFirstIndex() returning the initial position of the selection, it returns the smallest index that changed - this could be the start or end position).
Am I going about this the wrong way, or is this a bit of a flaw in the ListSelectionEvent class?
This behaviour seems odd to me, I cant think of how any use could come of it, why would Sun build this in like that?
Any help would be greatly appreciated.
colr__
It seems that the ListSelectionEvent is only interested in the changes in list selections. More specific information is available from the list and/or its model, such as, what values or which indices are selected.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class SelectionTest
{
public SelectionTest()
{
JList list = getList();
list.getSelectionModel().addListSelectionListener(new ListSelector());
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(list);
f.setSize(300,300);
f.setLocation(200,200);
f.setVisible(true);
}
private JList getList()
{
String[] items = new String[8];
for(int j = 0; j < items.length; j++)
items[j] = "item " + (j + 1);
return new JList(items);
}
public static void main(String[] args)
{
new SelectionTest();
}
}
class ListSelector implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent e)
{
if(!e.getValueIsAdjusting())
{
ListSelectionModel model = (ListSelectionModel)e.getSource();
// selection mode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
int
anchor = model.getAnchorSelectionIndex(),
lead= model.getLeadSelectionIndex(),
min= model.getMinSelectionIndex(),
max= model.getMaxSelectionIndex();
System.out.println("anchor = " + anchor + "\n" +
"lead= " + lead + "\n" +
"min= " + min + "\n" +
"max= " + max + "\n" +
"************");
}
}
}
hmm . . .
Using the above code snipets, I got the same output for all indices for some reason (they are all the destination index).
The code below is what I have just now. Whenever I implement this though, because I set the selected index from within the valueChanged() method, the valueChanged() method gets called again recursively, which (I think) goes on forever, eventually throwing an exceptio.
(I cant catch the Exception from within valueChanged, so Im not sure about where it comes from, but I do know that valueChanged() in this implementation gets called a large number of times when it should only happen once - Im sure this is due to this recursive-call side effect.
I've tried removing the default listener object, but this has no effect.
public class JListExt extends JList{
private DefaultListSelectionModel model;
private ListSelectionListener muteListener;
public JListExt(Vector data){
super(data);
muteListener = new MuteListener();
}
protected ListSelectionModel createSelectionModel(){
model = (DefaultListSelectionModel) super.createSelectionModel();
return model;
}
public void allowSelection(boolean allow){
if (allow)
model.removeListSelectionListener(muteListener);
else
model.addListSelectionListener(muteListener);
}
private class MuteListener implements ListSelectionListener{
public void valueChanged(ListSelectionEvent e){
if(!e.getValueIsAdjusting()){
int toIndex = getSelectedIndex();
int first = e.getFirstIndex();
int last = e.getLastIndex();
if (toIndex == first){
setSelectedIndex(last);
}
else{
setSelectedIndex(first);
}
}
}
}
}