If a selected index on a JList is clicked, I want it to de-select. In other words, clicking on the indices actually toggles their selection. Didn\'t look like this was suppo
I know that this question already has an accepted answer, but I thought that I'd expand a bit, since I ended up stuck on this task for a few hours.
I was trying to implement a click-to-deselect action for selected items, but my list implementation requires the use of Single-Selection mode, specified by
JList jlist = new JList(new DefaultListModel());
jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
Unfortunately, this led to exceptions and redundant calls for many of the solutions for the click-to-deselect problem on many SO questions, including this answer by FuryComptuers above. Due to code in DefaultListSelectionModel.class, specifically in the addSelectionInterval(int index0, int index1) and removeSelectionInterval(int index0, int index1) methods, which calls back to the setSelectionInterval(int index0, int index1) method, caused a circular call that leads to (obviously) exceptions. This "problem" code can be seen below.
// If we only allow a single selection, channel through
// setSelectionInterval() to enforce the rule.
if (getSelectionMode() == SINGLE_SELECTION) {
setSelectionInterval(index0, index1);
return;
}
Sawas Dalkitsis' answer solved this problem, but would still act weird when dragging the mouse on a selected item (the selected item will select and de-select itself over and over while dragging the mouse). This wouldn't seem like a problem, but (apparently) I have a shaky hand, and minor mouse movements while clicked resulted in unwanted behavior. I combined Sawas Dalkitsis answer and FuryComptuers's answer to get the following code, which seems to work as desired:
JList jlist = new JList(new DefaultListModel());
jList.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
boolean gestureStarted = false;
@Override
public void setSelectionInterval(int index0, int index1) {
if(!gestureStarted){
if (index0==index1) {
if (isSelectedIndex(index0)) {
removeSelectionInterval(index0, index0);
return;
}
}
super.setSelectionInterval(index0, index1);
}
gestureStarted = true;
}
@Override
public void addSelectionInterval(int index0, int index1) {
if (index0==index1) {
if (isSelectedIndex(index0)) {
removeSelectionInterval(index0, index0);
return;
}
super.addSelectionInterval(index0, index1);
}
}
@Override
public void setValueIsAdjusting(boolean isAdjusting) {
if (isAdjusting == false) {
gestureStarted = false;
}
}
});
jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
Note: I didn't check this against the ListSelectionModel.SINGLE_INTERVAL_SELECTION, as Sawas Dalkitsis did, so use caution if implementing it in that case.