使用AbstractTableModel获取JTable中选定的行

我有一个JTable使用AbstractTableModel ,我有一个JCheckBox在第一列选择行。 现在,我需要从被检查的表中选择所选的行。 现在,我顺序遍历从第一行到最后一行,并获取所有选定的行,如下所示,

 List<Integer> selectedRows = new ArrayList<Integer>(); for(int i = 0; i < table.getRowCount(); i++) { if((Boolean) table.getValuAt(i, 0)) { selectedRows.add(i); } } 

这里的问题是,我需要遍历所有的行时,我需要得到选定的行。 现在我有10到20行。 但是在将来我会得到5000行左右。 我的问题是,如果有5000行,如果用户只选择5000nd(最后一条记录)行,那么我需要遍历所有5000行,以获得选定的行。 我认为这不是一个好方法。

我想要实现的一种方法是,添加一个监听器到JCheckBox列,这样当有变化(SELECTED/DESELECTED)我需要更新监听器类中所选行的数组。 在这个监听器类中,当用户选择一个JCheckBox我需要调用table.getSelectedRow(..) ,如果选择了JCheckBox则需要存储。

有没有更好的方法?

在下面的例子中, TableModel更新了在setValueAt()的实现中Set<Integer> checkedSet<Integer> checked 。 相邻JList的模型监听表格的模型并显示当前选定的行号。 该示例假定选定行的数量与行数相比较小。 注意TreeSet的使用,它的迭代器保留了元素的自然顺序。

图片

 import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridLayout; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; /** @see http://stackoverflow.com/a/13919878/230513 */ public class CheckTable { private static final CheckModel model = new CheckModel(5000); private static final JTable table = new JTable(model) { @Override public Dimension getPreferredScrollableViewportSize() { return new Dimension(150, 300); } }; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame f = new JFrame("CheckTable"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1, 0)); f.add(new JScrollPane(table)); f.add(new DisplayPanel(model)); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } }); } private static class DisplayPanel extends JPanel { private DefaultListModel dlm = new DefaultListModel(); private JList list = new JList(dlm); public DisplayPanel(final CheckModel model) { super(new GridLayout()); this.setBorder(BorderFactory.createTitledBorder("Checked")); this.add(new JScrollPane(list)); model.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { dlm.removeAllElements(); for (Integer integer : model.checked) { dlm.addElement(integer); } } }); } } private static class CheckModel extends AbstractTableModel { private final int rows; private List<Boolean> rowList; private Set<Integer> checked = new TreeSet<Integer>(); public CheckModel(int rows) { this.rows = rows; rowList = new ArrayList<Boolean>(rows); for (int i = 0; i < rows; i++) { rowList.add(Boolean.FALSE); } } @Override public int getRowCount() { return rows; } @Override public int getColumnCount() { return 2; } @Override public String getColumnName(int col) { return "Column " + col; } @Override public Object getValueAt(int row, int col) { if (col == 0) { return row; } else { return rowList.get(row); } } @Override public void setValueAt(Object aValue, int row, int col) { boolean b = (Boolean) aValue; rowList.set(row, b); if (b) { checked.add(row); } else { checked.remove(row); } fireTableRowsUpdated(row, row); } @Override public Class<?> getColumnClass(int col) { return getValueAt(0, col).getClass(); } @Override public boolean isCellEditable(int row, int col) { return col == 1; } } } 

我同意kleopatra。 当您创建AbstractTableModel的子类时,您将覆盖setValue(Object值,int rowIndex,int colIndex)。 在你重写的方法中,你只需检查列是否与你的复选框,如果是的话,适当更新内部数据结构。 您还可以添加一个方法getCheckedRows(),该方法返回一个List <Integer>,其中复选框已被选中。