After adding a TableRowSorter adding values to model cause java.lang.IndexOutOfBoundsException: Invalid range

steve picture steve · May 29, 2011 · Viewed 11.4k times · Source

After adding a TableRowSorter to a table and its corresponding model any corresponding adds specifically at firetabletablerowsinserted cause exceptions. It is clear from testing that the GetRowCount() is returning a value past the models range. However it does not make sense to me how to continue to add values to the table after a sorter or filter has been added?

As an example, I set the row filter before adding anything to the table then add a value to the table with the following calls in my model:

this.addRow(row, createRow(trans,row));
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

The rowcount is of size 1 and the exception is thrown:

java.lang.IndexOutOfBoundsException: Invalid range
at javax.swing.DefaultRowSorter.checkAgainstModel(Unknown Source)
at javax.swing.DefaultRowSorter.rowsInserted(Unknown Source)
at com.gui.model

If I do the same steps without first adding the sorter everything is fine. I assumed that possibly I needed to notify the model that the sorter may have made changes and tried the following but still returns an exception:

this.addRow(row, createRow(trans,row));
this.fireTableStructureChanged()
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

I even tried to notify the sorter inside the model that a value has been added to the model before calling fire like below but it fails as well:

 this.addRow(row, createRow(trans,row));
 if(sorter.getRowFilter() != null){
      //if a sorter exists we are in add notify sorter
      sorter.rowsInserted(getRowCount(), getRowCount());
  }
  this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

Lastly, I hard coded the FireTableRowsInsterted(0,0) and it does not throw any exception. But nothing gets added to table? So, I know it is definitely some type of OutOfBounds issue. I have looked all over and cannot seem to find the answer. If anyone has any idea how this is suppose to work it be very helpful. Here is code that sets the sorter inside jpanel:

    messageTable.setRowSorter(null);
     HttpTransactionTableModel m = getTransactionTableModel();
     final int statusIndex = m.getColIndex("status");
     RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
           public boolean include(Entry<? extends Object, ? extends Object> entry) {

               for(char responseCode:responseCodes)
               {
                   if (entry.getStringValue(statusIndex).startsWith(Character.toString(responseCode))) {
                         return true;
                       }
               }


             // None of the columns start with "a"; return false so that this
             // entry is not shown
             return false;
           }
         };


        m.sorter.setRowFilter(startsWithAFilter);
        messageTable.setRowSorter(m.sorter);

Here is code inside my model that adds value to model:

public void update(Observable o, Object evt) {
    if (evt instanceof ObservableEvent<?>) {

        ObservableEvent<?> event = (ObservableEvent<?>) evt;

        if (event.getElement() instanceof HttpTransaction) {

            HttpTransaction trans = (HttpTransaction) event.getElement();

            // handle adding of an element
            if (event.getAction() == PUT) {

                if (includeTransaction(trans)) {

                    // handle request elements
                    if (trans.getRequest() != null && idMap.get(trans.getID()) == null) {

                        idMap.put(trans.getID(), count++);
                       // transactionManager.save(trans);
                        int row = idMap.get(trans.getID());
                        this.addRow(row, createRow(trans,row));
                        if(sorter.getRowFilter() != null){
                            sorter.rowsInserted(getRowCount(), getRowCount());
                        }
                        this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

                    }

Answer

Paul picture Paul · Jun 3, 2011

You have an out by 1 error. The correct code for firing the event is:

this.fireTableRowsInserted(this.getRowCount()-1, this.getRowCount()-1);