JTable sortieren: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
(Die Seite wurde neu angelegt: „Mit Java 1.6 wurde Swing weiterentwickelt. Unter anderem kann die JTable nun sortiert werden. Für die Sortierung muss man beim JTable einen RowSorter<? extends ...“)
 
K
 
(7 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
Mit Java 1.6 wurde Swing weiterentwickelt. Unter anderem kann die JTable nun sortiert werden.
 
Mit Java 1.6 wurde Swing weiterentwickelt. Unter anderem kann die JTable nun sortiert werden.
  
Für die Sortierung muss man beim JTable einen RowSorter<? extends TableModel> über die Methode setRowSorter registrieren. Die JTable wird diesen RowSorter benutzen um die Einträge des TableModels hin und her zu schieben.
+
Für die Sortierung muss man beim {{JAPI|JTable}} einen <code>RowSorter<? extends TableModel></code> über die Methode <code>setRowSorter()</code> registrieren. Die JTable wird diesen {{JAPI|RowSorter}} benutzen, um die Einträge des {{JAPI|TableModel}}s hin und her zu schieben.
  
 
===1. Der TableRowSorter===
 
===1. Der TableRowSorter===
Zwar wäre es möglich einen RowSorter selbst zu implementieren, die weitaus einfachere Variante ist aber die Benutzung der Klasse TableRowSorter.
+
Zwar wäre es möglich einen RowSorter selbst zu implementieren, die weitaus einfachere Variante ist aber die Benutzung der Klasse {{JAPI|TableRowSorter}}.
Der unkonfigurierte TableRowSorter sortiert jeweils eine Spalte. Sollten die Elemente dieser Spalte eine natürliche Ordnung (durch das Interface Comparable definiert) haben, so wird diese Ordnung benutzt. Andernfalls werden die Elemente in Strings umgewandelt, und mittels eines Collators verglichen.
+
Der unkonfigurierte TableRowSorter sortiert jeweils eine Spalte. Sollten die Elemente dieser Spalte eine natürliche Ordnung (durch das Interface {{JAPI|Comparable}} definiert) haben, so wird diese Ordnung benutzt. Andernfalls werden die Elemente in Strings umgewandelt, und mittels eines Collators verglichen.
  
Das sieht dann folgendermassen aus:
+
Das sieht dann folgendermaßen aus:
<code=java>
+
<syntaxhighlight lang="java">
 
import java.awt.*;
 
import java.awt.*;
 
import java.util.Random;
 
import java.util.Random;
Zeile 85: Zeile 85:
 
     }
 
     }
 
}
 
}
</code=java>
+
</syntaxhighlight>
  
<code=java>
+
<syntaxhighlight lang="java">
 
// Ein Renderer für java.awt.Point
 
// Ein Renderer für java.awt.Point
 
public class PointRender extends DefaultTableCellRenderer{
 
public class PointRender extends DefaultTableCellRenderer{
Zeile 98: Zeile 98:
 
             hasFocus,  row, column );
 
             hasFocus,  row, column );
 
     }
 
     }
}</code=java>
+
}</syntaxhighlight>
  
 
[[Bild:JTableSort1.png]]
 
[[Bild:JTableSort1.png]]
  
 
===2. Ein eigener Comparator===
 
===2. Ein eigener Comparator===
Im Beispiel des 1. Abschnittes wurden die String- und die Integer-Spalte sinnvoll sortiert, die Point-Spalte sah hingegen komisch aus. Damit auch diese Spalte sinnvoll sortiert wird (ohne dass man eine neue Point-Klasse implementiert) muss man einen Comparator bereitstellen. Dieser Comparator kann man über die Methode setComparator des TableRowSorters einbinden.  
+
Im Beispiel des 1. Abschnittes wurden die {{JAPI|String}}- und die {{JAPI|Integer}}-Spalte sinnvoll sortiert, die {{JAPI|Point}}-Spalte sah hingegen komisch aus. Damit auch diese Spalte sinnvoll sortiert wird (ohne dass man eine neue Point-Klasse implementiert), muss man einen {{JAPI|Comparator}} bereitstellen. Dieser Comparator kann man über die Methode <code>setComparator()</code> des TableRowSorters einbinden.  
  
 
Der Code vom Beispiel oben leicht abgeändert:
 
Der Code vom Beispiel oben leicht abgeändert:
<code=java>
+
<syntaxhighlight lang="java">
 
import java.awt.*;
 
import java.awt.*;
 
import java.util.Comparator;
 
import java.util.Comparator;
Zeile 143: Zeile 143:
  
 
     [...]
 
     [...]
}</code=java>
+
}</syntaxhighlight>
  
<code=java>
+
<syntaxhighlight lang="java">
 
// Ein Comparator für Punkte
 
// Ein Comparator für Punkte
 
public class PointComparator implements Comparator<Point>{
 
public class PointComparator implements Comparator<Point>{
Zeile 160: Zeile 160:
 
             return 0;
 
             return 0;
 
     }
 
     }
}</code=java>
+
}</syntaxhighlight>
 
Das Resultat: die Punkte werden zuerst nach der x, dann nach der y-Koordinate sortiert:
 
Das Resultat: die Punkte werden zuerst nach der x, dann nach der y-Koordinate sortiert:
 +
 
[[Bild:JTableSort2.png]]
 
[[Bild:JTableSort2.png]]
  
===3. Weitere Methoden==
+
===3. Weitere Methoden===
Der TableRowSorter bietet eine Reihe weitere Methoden die Aufmerksamkeit verdienen:
+
Der TableRowSorter bietet eine Reihe weiterer Methoden, die Aufmerksamkeit verdienen:
*setStringConverter setzt ein Delegate um aus Objects Strings zu generieren. Praktisch dasselbe was die Methode toString macht. Wenn ein TableStringConverter gesetzt ist, wird dieser Converter anstelle der toString-Methode benutzt, um einen sortierbaren String aus unbekannten Objekten zu generieren. Vorteilhaft ist dieses vorgehen, wenn die toString-Methode nicht überschrieben werden kann (weil die Objekte z.B. aus einer Library kommen), oder verschiedene Tabellen nach unterschiedlichen Kriterien sortieren sollen.
+
*<code>setStringConverter()</code> setzt ein Delegate um aus Objects Strings zu generieren. Praktisch das Selbe, was die Methode <code>toString()</code> macht. Wenn ein {{JAPI|TableStringConverter}} gesetzt ist, wird dieser Converter an Stelle der toString()-Methode benutzt, um einen sortierbaren String aus unbekannten Objekten zu generieren. Vorteilhaft ist dieses Vorgehen, wenn die toString()-Methode nicht überschrieben werden kann (weil die Objekte z.B. aus einer Library kommen), oder verschiedene Tabellen nach unterschiedlichen Kriterien sortieren sollen.
*setMaxSortKeys sagt dem Sorter, wieviele Spalten beim Sortieren beachtet werden sollen. Angenommen der Wert ist auf 3, der Benutzer sortiert zuerst Spalte 2, dann 1: sollte nun in Spalte 1 ein Element doppelt vorkommen, so werden die Zeilen nach der 2. Spalte sortiert. Würde der Benutzer noch auf die 4. Spalte klicken, so würde zuerst nach der 4., dann nach der 1., dann nach der 2. Spalte sortiert.
+
*<code>setMaxSortKeys()</code> sagt dem Sorter, wie viele Spalten beim Sortieren beachtet werden sollen. Angenommen der Wert ist auf 3, der Benutzer sortiert zuerst Spalte 2, dann 1: sollte nun in Spalte 1 ein Element doppelt vorkommen, so werden die Zeilen nach der 2. Spalte sortiert. Würde der Benutzer noch auf die 4. Spalte klicken, so würde zuerst nach der 4., dann nach der 1., dann nach der 2. Spalte sortiert.
*setRowFilter setzt einen RowFilter. Der RowFilter entscheidet in seiner include-Methode zeilenweise, welche Zeilen angezeigt werden sollten. Ein RowFilter eignet sich z.B. für eine Suchfunktion: sobald der Benutzer in ein Textfeld etwas eintippt, erlaubt der RowFilter nur noch diejenigen Daten, welche zu dem eingetippten Text passen. Der Sorter kann über die Methode sort aufgefordert werden, den veränderten Filter zu benutzen.
+
*<code>setRowFilter()</code> setzt einen {{JAPI|RowFilter}}. Der RowFilter entscheidet in seiner include()-Methode zeilenweise, welche Zeilen angezeigt werden sollten. Ein RowFilter eignet sich z.B. für eine Suchfunktion: sobald der Benutzer in ein Textfeld etwas eintippt, erlaubt der RowFilter nur noch diejenigen Daten, welche zu dem eingetippten Text passen. Der Sorter kann über die Methode sort aufgefordert werden, den veränderten Filter zu benutzen.
  
[[Kategorie:Java]]
+
[[Kategorie:Tutorials (Java)]]
[[Kategorie:Java (Tutorial)]]
+
[[Kategorie:JTable]]
 +
[[Kategorie:Swing]]

Aktuelle Version vom 28. März 2018, 09:35 Uhr

Mit Java 1.6 wurde Swing weiterentwickelt. Unter anderem kann die JTable nun sortiert werden.

Für die Sortierung muss man beim JTable einen RowSorter<? extends TableModel> über die Methode setRowSorter() registrieren. Die JTable wird diesen RowSorter benutzen, um die Einträge des TableModels hin und her zu schieben.

1. Der TableRowSorter

Zwar wäre es möglich einen RowSorter selbst zu implementieren, die weitaus einfachere Variante ist aber die Benutzung der Klasse TableRowSorter. Der unkonfigurierte TableRowSorter sortiert jeweils eine Spalte. Sollten die Elemente dieser Spalte eine natürliche Ordnung (durch das Interface Comparable definiert) haben, so wird diese Ordnung benutzt. Andernfalls werden die Elemente in Strings umgewandelt, und mittels eines Collators verglichen.

Das sieht dann folgendermaßen aus:

import java.awt.*;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.*;

public class JTableDemo{
    public static void main( String[] args ){
        // Ein TableModel mit zufälligen Werten füllen
        TableModel model = randomModel();
        
        // Die JTable initialisieren
        JTable table = new JTable( model );
        table.setDefaultRenderer( Point.class, new PointRender());
        
        // Der TableRowSorter wird die Daten des Models sortieren
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>();
        
        // Der Sorter muss dem JTable bekannt sein
        table.setRowSorter( sorter );
        
        // ... und der Sorter muss wissen, welche Daten er sortieren muss
        sorter.setModel( model );

        JFrame frame = new JFrame( "Demo" );
        frame.getContentPane().add( new JScrollPane( table ) );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
    }
    
    // Diese Methode generiert ein TableModel mit zufälligen Werten
    private static TableModel randomModel(){
        Object[] names = { "String", "Integer", "Point" };
        
        DefaultTableModel model = new DefaultTableModel( names, 0 ){
            @Override
            public Class<?> getColumnClass( int column ) {
                switch( column ){
                    case 0: return String.class;
                    case 1: return Integer.class;
                    case 2: return Point.class;
                    default: return Object.class;
                }
            }
        };

        Random random = new Random();
        
        for( int i = 0; i < 100; i++ ){
            Object[] row = {
                    randomString( random ),
                    randomInt( random ),
                    new Point( randomInt( random ), randomInt( random ))
            };
            
            model.addRow( row );
        }
        
        return model;
    }
    
    // Generiert einen zufälligen String
    private static String randomString( Random random ){
        int length = random.nextInt( 4 ) + 4;
        StringBuilder result = new StringBuilder( length );
        for( int i = 0; i < length; i++ )
            result.append( (char)('a' + random.nextInt( 'z' - 'a' + 1 )));
        return result.toString();
    }
    
    // Generiert einen zufälligen int
    private static int randomInt( Random random ){
        return random.nextInt( 1000 ) + 1;
    }
}
// Ein Renderer für java.awt.Point
public class PointRender extends DefaultTableCellRenderer{
    @Override
    public Component getTableCellRendererComponent( JTable table, Object value, 
            boolean isSelected, boolean hasFocus, int row, int column ) {
        Point point = (Point)value;
        String text = point.x + " / " + point.y;
        return super.getTableCellRendererComponent( table, text, isSelected,
            hasFocus,  row, column );
    }
}

JTableSort1.png

2. Ein eigener Comparator

Im Beispiel des 1. Abschnittes wurden die String- und die Integer-Spalte sinnvoll sortiert, die Point-Spalte sah hingegen komisch aus. Damit auch diese Spalte sinnvoll sortiert wird (ohne dass man eine neue Point-Klasse implementiert), muss man einen Comparator bereitstellen. Dieser Comparator kann man über die Methode setComparator() des TableRowSorters einbinden.

Der Code vom Beispiel oben leicht abgeändert:

import java.awt.*;
import java.util.Comparator;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.*;

public class JTableDemo{
    public static void main( String[] args ){
        // Ein TableModel mit zufälligen Werten füllen
        TableModel model = randomModel();
        
        // Die JTable initialisieren
        JTable table = new JTable( model );
        table.setDefaultRenderer( Point.class, new PointRender());
        
        // Der TableRowSorter wird die Daten des Models sortieren
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>();
        
        // Der Sorter muss dem JTable bekannt sein
        table.setRowSorter( sorter );
        
        // ... und der Sorter muss wissen, welche Daten er sortieren muss
        sorter.setModel( model );

        // Den Comparator für die 2. Spalte (mit den Points) setzen.
        sorter.setComparator( 2, new PointComparator());
        
        JFrame frame = new JFrame( "Demo" );
        frame.getContentPane().add( new JScrollPane( table ) );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
    }

    [...]
}
// Ein Comparator für Punkte
public class PointComparator implements Comparator<Point>{
    public int compare( Point o1, Point o2 ) {
        if( o1.x < o2.x )
            return -1;
        else if( o1.x > o2.x )
            return 1;
        else if( o1.y < o2.y )
            return -1;
        else if( o1.y > o2.y )
            return 1;
        else
            return 0;
    }
}

Das Resultat: die Punkte werden zuerst nach der x, dann nach der y-Koordinate sortiert:

JTableSort2.png

3. Weitere Methoden

Der TableRowSorter bietet eine Reihe weiterer Methoden, die Aufmerksamkeit verdienen:

  • setStringConverter() setzt ein Delegate um aus Objects Strings zu generieren. Praktisch das Selbe, was die Methode toString() macht. Wenn ein TableStringConverter gesetzt ist, wird dieser Converter an Stelle der toString()-Methode benutzt, um einen sortierbaren String aus unbekannten Objekten zu generieren. Vorteilhaft ist dieses Vorgehen, wenn die toString()-Methode nicht überschrieben werden kann (weil die Objekte z.B. aus einer Library kommen), oder verschiedene Tabellen nach unterschiedlichen Kriterien sortieren sollen.
  • setMaxSortKeys() sagt dem Sorter, wie viele Spalten beim Sortieren beachtet werden sollen. Angenommen der Wert ist auf 3, der Benutzer sortiert zuerst Spalte 2, dann 1: sollte nun in Spalte 1 ein Element doppelt vorkommen, so werden die Zeilen nach der 2. Spalte sortiert. Würde der Benutzer noch auf die 4. Spalte klicken, so würde zuerst nach der 4., dann nach der 1., dann nach der 2. Spalte sortiert.
  • setRowFilter() setzt einen RowFilter. Der RowFilter entscheidet in seiner include()-Methode zeilenweise, welche Zeilen angezeigt werden sollten. Ein RowFilter eignet sich z.B. für eine Suchfunktion: sobald der Benutzer in ein Textfeld etwas eintippt, erlaubt der RowFilter nur noch diejenigen Daten, welche zu dem eingetippten Text passen. Der Sorter kann über die Methode sort aufgefordert werden, den veränderten Filter zu benutzen.