I want to restrict the row selection in JTable to only 2 rows. If the user tries to select a third row (Ctrl + click), the oldest selection in the table should be programmatically deselected. To achieve this, I have added a ListSelectionListener to the table.
In the following sample, the "clearSelection()"
doesn't seem to work.
Please advice if there is a simpler or elegant way to achieve the same.
package test;
import java.util.Arrays;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class JTableDemo {
public static void main(String[] argv) {
Vector rowData = new Vector();
for (int i = 0; i < 10; i++) {
Vector colData = new Vector(Arrays.asList("row" + (i + 1)));
rowData.add(colData);
}
String[] columnNames = { "header" };
Vector columnNamesV = new Vector(Arrays.asList(columnNames));
JTable table = new JTable(rowData, columnNamesV);
table.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setColumnSelectionAllowed(false);
SelectionListener listener = new SelectionListener(table);
table.getSelectionModel().addListSelectionListener(listener);
JFrame f = new JFrame();
f.setSize(300, 300);
f.add(new JScrollPane(table));
f.setVisible(true);
}
private static class SelectionListener implements ListSelectionListener {
JTable table;
int prevSelectedRow;
int oldSelectedRow = -1;
SelectionListener(JTable table) {
this.table = table;
}
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
if (e.getSource() == table.getSelectionModel() && table.getRowSelectionAllowed()) {
int[] selectedRows = table.getSelectedRows();
if (selectedRows.length == 1) {
prevSelectedRow = selectedRows[0];
return;
}
if (selectedRows.length > 1) {
int currentSelectedRow = -1;
System.out.println("The first and last indexes are : " + e.getFirstIndex() + ", " + e.getLastIndex());
if (oldSelectedRow == -1) {
for (int i = 0; i < selectedRows.length; i++) {
if (prevSelectedRow != selectedRows[i]) {
currentSelectedRow = selectedRows[i];
break;
}
}
table.getSelectionModel().removeListSelectionListener(this);
table.clearSelection();
table.setRowSelectionInterval(prevSelectedRow, prevSelectedRow);
oldSelectedRow = prevSelectedRow;
prevSelectedRow = currentSelectedRow;
table.addRowSelectionInterval(currentSelectedRow, currentSelectedRow);
table.getSelectionModel().addListSelectionListener(this);
} else {
for (int i = 0; i < selectedRows.length; i++) {
if (prevSelectedRow != selectedRows[i] && oldSelectedRow != selectedRows[i]) {
currentSelectedRow = selectedRows[i];
break;
}
}
table.getSelectionModel().removeListSelectionListener(this);
table.clearSelection();
table.setRowSelectionInterval(prevSelectedRow, prevSelectedRow);
oldSelectedRow = prevSelectedRow;
prevSelectedRow = currentSelectedRow;
table.addRowSelectionInterval(currentSelectedRow, currentSelectedRow);
table.getSelectionModel().addListSelectionListener(this);
}
}
}
}
}
}
You can extend the
DefaultListSelectionModel
and override theaddSelectionInterval(...)
method. Then you add you custom selection model to the table.