在Jtable中排序行时出错

时间:2013-10-26 11:19:16

标签: java swing tablecellrenderer tablerowsorter

我正在尝试在我的Jtable上设置RowSorter,我使用方法setAutoCreateRowSorter(Boolean b)对行进行排序

table.setAutoCreateRowSorter(true);

但当我将表格设为rawSorted时,我收到一个奇怪的错误!

当我想要删除一行时,冲突是可见的,我使用了fireTableRowsDeleted()

int raw = table.getSelectedRow();  // the index of raw that i want to delete it
System.out.println(raw);
model.delte_raw(raw); // model is my table model

public void delte_raw(int raw)
         {
             if (!ls.isEmpty()) {
         this.fireTableRowsDeleted(raw+1, raw);
         ls.remove(raw);
         }

我想告诉你在2种情况下返回代码的结果是什么:

案例1:

当我把我的桌子做成没有原始的时候:

table.setAutoCreateRowSorter(false);

当我删除一行时,一切都成功。

案例2:

当我把桌子作为rawsorted时:

table.setAutoCreateRowSorter(true);

当我删除一行时,我收到如下错误:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid range
    at javax.swing.DefaultRowSorter.checkAgainstModel(DefaultRowSorter.java:921)
    at javax.swing.DefaultRowSorter.rowsDeleted(DefaultRowSorter.java:878)
    at javax.swing.JTable.notifySorter(JTable.java:4277)
    at javax.swing.JTable.sortedTableChanged(JTable.java:4121)
    at javax.swing.JTable.tableChanged(JTable.java:4398)
    at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
    at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)

我认为错误发生在我的defaultRowSorter中,因此我将具体的cellRenderer定义如下:

//    final TableCellRenderer r = table.getTableHeader().getDefaultRenderer();
//TableCellRenderer wrapper = new TableCellRenderer() {
//            private Icon ascendingIcon = new ImageIcon("images/e.png");
//            private Icon descendingIcon = new ImageIcon("images/e.png");
//
//    @Override
//    public Component getTableCellRendererComponent(JTable table,
//            Object value, boolean isSelected, boolean hasFocus,
//            int row, int column) 
//    {
//        Component comp = r.getTableCellRendererComponent(table, value, isSelected, 
//            hasFocus, row, column);
//        if (comp instanceof JLabel) {
//            JLabel label = (JLabel) comp;
//            label.setIcon(getSortIcon(table, column));
//        }
//        return comp;
//    }
//
//    /**
//     * Implements the logic to choose the appropriate icon.
//     */
//    private Icon getSortIcon(JTable table, int column) {
//        SortOrder sortOrder = getColumnSortOrder(table, column);
//        if (SortOrder.UNSORTED == sortOrder) {
//            return null;
//        }
//        return SortOrder.ASCENDING == sortOrder ? ascendingIcon : descendingIcon;
//    }
//
//    private SortOrder getColumnSortOrder(JTable table, int column) {
//        if (table == null || table.getRowSorter() == null) {
//            return SortOrder.UNSORTED;
//        }
//        List<? extends RowSorter.SortKey> keys = table.getRowSorter().getSortKeys();
//        if (keys.size() > 0) {
//                    RowSorter.SortKey key = keys.get(0);
//            if (key.getColumn() == table.convertColumnIndexToModel(column)) {
//                return key.getSortOrder();
//            }
//        }
//        return SortOrder.UNSORTED;
//    }
//
//};
//table.getTableHeader().setDefaultRenderer(wrapper);

但是,同样的错误!

为什么会出现此错误?我搜索了很多,但要么我使用了错误的关键字,要么在互联网上没有简单的解决方案。

1 个答案:

答案 0 :(得分:2)

在你的桌子模型中:

public void delte_raw(int raw) {
    if (!ls.isEmpty()) {
        this.fireTableRowsDeleted(raw+1, raw); // why raw+1 ???
        ls.remove(raw);
    }
}

当您的桌面模型从AbstractTableModel延伸并查看fireTableRowsDeleted(int firstRow, int lastRow) javadoc:

  

通知所有侦听器[firstRow, lastRow]范围内的行,   包容性,已被删除。

所以它应该是:

public void delte_raw(int raw) {
    if (!ls.isEmpty()) {            
        ls.remove(raw); // remove the row index from the List and then fire the event
        fireTableRowsDeleted(raw, raw);
    }
}

了解异常来源:查看DefaultRowSorter.checkAgainstModel(int firstRow, int endRow)实施:

private void checkAgainstModel(int firstRow, int endRow) {
    if (firstRow > endRow || firstRow < 0 || endRow < 0 ||
            firstRow > modelRowCount) {
        throw new IndexOutOfBoundsException("Invalid range");
    }
}

如您所见,使用[raw+1,raw]范围调用此方法会导致IndexOutOfBoundsException

修改

正如@mKorbel巧妙地指出的那样,我完全忽略了这一点:

int raw = table.getSelectedRow();  // this is the index in the view
model.delte_raw(raw); // convert raw in the right model index is needed

您需要在正确的模型索引中转换raw。否则它可能会导致副作用,因为在排序表中,视图中的选定索引很可能与其相关模型的索引不同:

int raw = table.getSelectedRow();  // this is the index in the view
model.delte_raw(table.convertRowIndexToModel(raw)); // perfect

请参阅JTable.convertRowIndexToModel(int viewRowIndex)