# Invalid Range - Fehler bei TableRowSorter / Tabelle



## Taste (6. Feb 2009)

Hallo,
ich folgendes Problem:

Ich habe eine Tabelle, der ich ein Model und ein ColumnModel verpasse und soweit ist auch alles gut.
Nun habe ich versucht, anhand der Beispiele in den FAQ's eine Sortierung zu aktivieren:

```
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( this.table.getModel() );
          this.table.setRowSorter( sorter );
```
Eigentlich ja kein Problem. Aber wenn ich dann Daten einfügen möchte mit:

```
final Vector v = new Vector();
            v.add( entry.getKey() );
            v.add( entry.getValue() );
            extMappingTable.getComponent().addRow( v );
```
Dann erhalte ich folgende Fehlermeldung:

Caused by: java.lang.IndexOutOfBoundsException: Invalid range
	at javax.swing.DefaultRowSorter.checkAgainstModel(DefaultRowSorter.java:904)
	at javax.swing.DefaultRowSorter.rowsInserted(DefaultRowSorter.java:844)
	at javax.swing.JTable.notifySorter(JTable.java:4208)
	at javax.swing.JTable.sortedTableChanged(JTable.java:4056)
	at javax.swing.JTable.tableChanged(JTable.java:4333)
	at com.test.wswing.WJTable.tableChanged(WJTable.java:236)
	at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:280)
	at javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTableModel.java:215)
	at com.test.client.table.HyperTableModel2.addRow(HyperTableModel2.java:261)
	at ...

Instanziiere und setze ich den TableRowSorter nach dem Hinzufügen der Rows, dann klappts problemlos, aber ich will doch eigentlich eine saubere Initialisierung der Tabelle haben, bevor ich Daten einfüge.

Hab ich da einen Gedankenfehler, oder was mache ich falsch?
Gruß, Nick


----------



## André Uhres (7. Feb 2009)

1234567890


----------



## Taste (8. Feb 2009)

Hallo André,

mein Fehler, Deine Erwartung passt schon.
Diese Methode:

```
extMappingTable.getComponent().addRow(v);
```
ruft auf dem TableModel addRow(...) auf.

Dass das TableModel noch nicht existieren könnte war auch eine Vermutung von mir, aber wenn ich mir direkt an dieser Stelle, wo ich den sorter setze

```
tabelModel.getRowCount()
```
aufrufe, dann bekomme ich 0 zurück und nicht etwa eine NPE.

Ich bekomme die Exception ja auch nicht beim Erzeugen und setzen des RowSortes, sondern beim Einfügen der Daten...

---------------------------------

Ich habe nun testhalber mal Folgendes implementiert:

```
// erst Daten setzen
final Vector v = new Vector();
v.add( entry.getKey() );
v.add( entry.getValue() );
extMappingTable.getComponent().addRow(v);

// dann Sorter erzeugen und setzen 
extMappingTable.getComponent().addRow( v );
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( this.table.getModel() );
          this.table.setRowSorter( sorter );
```
Dies funktioniert, aber ist ja wie schon gesagt in meinen Augen nicht ganz die richtige Reihenfolge, oder?
Wenn ich dann direkt danach eine weitere Zeile hinzufüge, dann erhalte ich wieder die gleiche Exception:

```
// eine weitere Zeile Daten setzen
final Vector v = new Vector();
v.add( entry.getKey() );
v.add( entry.getValue() );
extMappingTable.getComponent().addRow(v);
```

Was mag da falsch sein...
Herzlichen Gruß, Nick


----------



## André Uhres (8. Feb 2009)

1234567890


----------



## Ebenius (9. Feb 2009)

André Uhres hat gesagt.:
			
		

> "this.table.getModel()" könnte, wenn es denn nicht null ist, auf eine andere Instanz zeigen als "extMappingTable.getComponent()".


TableModel kann nach Erzeugung der Tabelle nicht null sein. JTable Source Code: 
	
	
	
	





```
public void setModel(TableModel dataModel) {
  if (dataModel == null) {
        throw new IllegalArgumentException("Cannot set a null TableModel");
  }
[...]
```


----------



## André Uhres (9. Feb 2009)

1234567890


----------



## Ebenius (9. Feb 2009)

Ein ganz einfaches "Du hast Recht" hätte meinem Ego doch genügt. ;-)


----------



## Taste (9. Feb 2009)

Ja, ihr habt beide Recht (nur fürs Ego  :wink

Nur leider ist es die gleiche Instanz. Ich hatte bloß den Code nicht mehr genau im Kopf. Ich greife schon direkt auf das Model der Tabelle zu, die ich da mit Daten befülle... Sorry, dass ich mich so missverständlich ausgedrückt habe.

Ich werde mich dem Problem morgen nochmal widmen.

Gruß, Nick

[Edit: Es ist doch leider wirklich die gleiche Instanz )]


----------



## André Uhres (9. Feb 2009)

1234567890


----------



## Ebenius (9. Feb 2009)

Zeig mal den Source-Code von _HyperTableModel2_. Ich gehe davon aus, Du sendest den Event an der falschen Stelle oder zählst RowCount an der falschen Stelle hoch, oder ähnliches.


----------



## André Uhres (9. Feb 2009)

1234567890


----------



## Ebenius (9. Feb 2009)

André Uhres hat gesagt.:
			
		

> Es ist wohl eher so, daß wir zwei verschiedene Instanzen von TableModels haben :wink:


Den letzten Kommentar von Taste hatte ich falsch gelesen... Hatte verstanden, es wären die gleichen Instanzen.


----------



## Taste (11. Feb 2009)

Also nun hab ich wieder einige Zeit debugged und Folgendes herausgefunden:

Es handelt sich definitiv um die selbe Instanz von dem Model.

Was fehl schlägt ist diese Methode in DefaultRowSorter:

```
private void checkAgainstModel(int firstRow, int endRow) {
        if (firstRow > endRow || firstRow < 0 || endRow < 0 ||
                firstRow > modelRowCount) {
            throw new IndexOutOfBoundsException("Invalid range");
        }
    }
```
Hier den gesamten Code des Models zu posten wäre wohl zuviel, aber diese Methode macht mich stutzig:

```
public void addRow( List aRowData )
   {
      List theRowData = ( aRowData != null ? aRowData : this.createEmptyRow() );
      this.myData.add( theRowData );
      this.fireTableRowsInserted( this.getRowCount(), this.getRowCount() );
   }
```
this.myData ist einfach nur eine lokale Liste und this.getRowCount() liefert nur die Länge dieser Liste...
Ich versuche nun zu verstehen, wo da überhaupt die Verbindung zur Tabelle ist... Kann doch eigentlich nur über die Methode  this.fireTableRowsInserted(...) gehen, oder?

Achso, das Model ist abgeleitet von AbstractTableModel, falls das Euch hilft.
Habt Ihr eine Idee für mich oder könnt mir das erklären?


----------



## Ebenius (11. Feb 2009)

Taste hat gesagt.:
			
		

> ```
> public void addRow( List aRowData )
> {
> List theRowData = ( aRowData != null ? aRowData : this.createEmptyRow() );
> ...


Deine letzte Zeile ist nicht bei _getRowCount()_, sondern bei _*getRowCount() - 1*_.

Dann geht's, stimmt's?

PS: Herr Uhres, ich liebe es, wenn ich recht habe :lol:

Ebenius


----------



## Taste (11. Feb 2009)

Schon möglich, dass Du Recht hast. 
Mir ist noch eingefallen, dass nur diese Bedingung erfüllt sein kann:

```
firstRow > modelRowCount
```
Daher muss die Exception kommen. 

Wie meinst Du das mit getRowCount() - 1?
Ich stehe wohl auf dem berühmt berüchtigten Schlauch...
Gruß, Nick


----------



## Ebenius (11. Feb 2009)

Richtig funktioniert es damit: 
	
	
	
	





```
public void addRow( List aRowData ) { 
      List theRowData = ( aRowData != null ? aRowData : this.createEmptyRow() ); 
      this.myData.add( theRowData ); 
      this.fireTableRowsInserted( this.getRowCount() - 1, this.getRowCount() - 1 ); 
}
```

Oder damit: 
	
	
	
	





```
public void addRow( List aRowData ) { 
      List theRowData = ( aRowData != null ? aRowData : this.createEmptyRow() );
      final int oldRowCount = this.getRowCount();
      this.myData.add( theRowData ); 
      this.fireTableRowsInserted( oldRowCount, oldRowCount ); 
}
```

Jetzt klar?

Ebenius


----------



## Taste (11. Feb 2009)

Ja, absolut!

DANKE!!! Du bist mein Held der Stunde!

So ein blöder Fehler in uraltem Code...


----------



## André Uhres (11. Feb 2009)

1234567890


----------

