Micha: JTable sortieren; Probleme mit leeren Zellen

Hallo,

ich möchte, dass die Spalten einer JTable sortierbar sind, wenn auf den Tabellenkopf der jeweiligen Spalte geklickt wird. Hierzu habe ich einen RowSorter hinzugefügt.

  
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( tableModel );  
table.setRowSorter( sorter );  

das funktioniert soweit auch ganz gut. Nachteilig ist, dass ich die Tabellendaten und somit die Zeilenanzahl vorher nicht kenne. In meiner Anwendung sieht der Nutzer zunächst eine leere Tabelle mit 20 Zeilen (20 ist fiktiv gewählt), die er mit Werten füllen kann. Ist der Anwender in der letzten Zeile angekommen, so hänge ich einfach eine weitere Zeile an, sodass endlos Daten in die Tabelle geschrieben werden können.
Wenn nun die Spalte sortiert wird, dann werden die leeren Zellen jedoch berücksichtigt und mitsortiert. Hat der Nutzer nur bspw. 5 Einträge in der Tabelle gemacht, so sieht er einmal 15 leere Zellen, bevor er seine Eingaben sieht - das erscheint mir nicht sonderlich nutzerfreundlich. Über die Comparator-Schnittstelle, welche ich an den Sorter anhängen kann:
sorter.setComparator( i, new AbsoluteValueComparator());
werden die null-Elemente leider nicht übergeben, sodass sie dort nicht (wie gewünscht) berücksichtigt werden können (so fern ich nichts übersehen habe).

Ich habe die Frage bereits im java-forum gestellt und auch eine Lösung bekommen. Diese baut aber darauf auf, dass ich Pseudowerte in die Tabelle setze, die immer ans Ende sortiert werden. Gibt es ggf. noch eine bessere Lösung, die allg. gültig ist?

Mit freundlichem Gruß
Micha

  1. Hallo Micha,

    Dieses Verhalten bei null-Referenzen steht fest in DefaultRowSorter drin.
    Ich verstehe ja nicht recht, wieso das so gemacht wurde, schon gar nicht, wieso man es nicht abschalten kann.

    DefaultRowSorter setzt allerdings nicht direkt auf dem Modell auf, sondern verwnedet einen ModelWrapper. Dadurch ist es möglich, die Werte, die der RowSorter zum Filtern und Sortieren sieht zu ersetzen, ohne etwas am Datenmodell zu ändern.

    Ich würde von TableRowSorter ableiten und dabei setModel wie folgt überschreiben:

      
    public static final Object NULL_OBJECT = new Object();  
      
    public void setModel(M model) {  
      super.setModel(model);  
      final ModelWrapper<M,Integer> wrapper = getModelWrapper();  
      setModelWrapper(new ModelWrapper<M,Integer> {  
      
            public M getModel() {  
                return wrapper.getModel();  
            }  
      
            public int getColumnCount() {  
                return wrapper.getColumnCount();  
            }  
      
            public int getRowCount() {  
                return wrapper.getRowCount();  
            }  
      
            public Object getValueAt(int row, int column) {  
                Object obj = wrapper.getValueAt(row, column);  
                return obj == null ? NULL_OBJECT : obj;  
            }  
      
            public String getStringValueAt(int row, int column) {  
                return wrapper.getStringValueAt(row, column);  
            }  
      
            public Integer getIdentifier(int index) {  
                return wrapper.getIdentifier(index);  
            }  
        }  
    }  
    
    

    Dann kannst Du einfach statt auf null in deinem Comparator auf NULL_OBJECT vergleichen. Das ist natürlich nicht so richtig sauber, vor allem, weil man sich darauf verlösst, dass setModelWrapper von TableRowSorter nur in setModel aufgerufen wird (was momentan so ist). Eine elegantere Methode scheint es aber nicht zu geben, wenn man nicht gleich einen eigenen RowSorter schreiben will.

    Grüße

    Daniel

    1. Hallo Daniel Thoma,

      Danke für Deine Antwort, das werde ich mal versuchen. Muß ich dann eigentlich, wie in dem Beispiel aus dem java-forum für jede Sortierrichtung einen eigenen Comparator schreiben und ihn jeweils zuweisen oder kann man das abkürzen?

      Mit freundlichem Gruß
      Micha