I'm somewhat new to Java, and especially new to tables, and I'm having a bit of trouble with one particular task.
I have a JTable that uses a custom table model that extends DefaultTableModel, and I've attached a TableRowSorter to the table. The sample application below has two buttons--one will load rows into the table and one will remove all selected rows from the table.
For some reason, if you select the last row in the table along with any other row, when you click the "Remove" button it will remove all selected rows except the last row. You can remove any other combination of rows and it works fine.
What's more, if you first click on the column header to sort the rows (even if the order of rows doesn't change), it will work correctly. If I add a line to explicitly sort the rows in the table after loading it, the problem "goes away", but I'd like to know why what I'm doing is incorrect.
To see the behavior, click the "Load" button to populate the table, select all of the rows in the table, then click the "Remove" button. It will remove all rows except the last one.
As the call to println shows, the first iteration through the loop reduces the selected row count by two. This behavior is consistent no matter how many rows you have in the table, but only if you've selected the last row in the table.
I'm using Java version 1.6.0_16. Any ideas as to what I'm doing wrong?
Thanks,
Joe
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.util.Arrays;
public class TableTest
extends JFrame
{
private JTable widgetTable;
private WidgetTableModel widgetTableModel;
public static void main(String[] args)
{
TableTest frame = new TableTest();
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public TableTest()
{
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
EventQueue.invokeLater(new Runnable() { public void run() { createUI(); } });
}
private void createUI()
{
this.setLayout(new BorderLayout());
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
loadPerformed();
}
});
this.add(loadButton, BorderLayout.NORTH);
widgetTableModel = new WidgetTableModel();
widgetTable = new JTable(widgetTableModel);
widgetTable.setRowSorter(new TableRowSorter<WidgetTableModel>(widgetTableModel));
this.add(new JScrollPane(widgetTable), BorderLayout.CENTER);
JButton removeButton = new JButton("Remove");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removePerformed();
}
});
this.add(removeButton, BorderLayout.SOUTH);
}
private void loadPerformed()
{
widgetTableModel.addRow(new Object[] {"Widget 1"});
widgetTableModel.addRow(new Object[] {"Widget 2"});
widgetTableModel.addRow(new Object[] {"Widget 3"});
widgetTableModel.addRow(new Object[] {"Widget 4"});
widgetTableModel.addRow(new Object[] {"Widget 5"});
}
private void removePerformed()
{
int selectedRow = widgetTable.getSelectedRow();
while (selectedRow >= 0) {
System.out.println("selectedRowCount=" + widgetTable.getSelectedRowCount());
int modelRow = widgetTable.convertRowIndexToModel(selectedRow);
widgetTableModel.removeRow(modelRow);
selectedRow = widgetTable.getSelectedRow();
}
}
}
class WidgetTableModel
extends DefaultTableModel
{
public WidgetTableModel()
{
this.addColumn("Column 1");
}
}