package de.tutorials.saban.table.datesorter;
import java.awt.Container;
import java.awt.FlowLayout;
import java.util.Calendar;
import java.util.Comparator;
import java.util.GregorianCalendar;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
/**
* Diese Klasse erstellt ein GUI mit einer Tabelle darin. Die Tabelle enthält
* Datums-Werte und diese sollen sortiert werden können. Da es für die
* Sortierung von Datums-Werten keine Standard-Implementierung gibt, muss man
* sich selbst eine basteln. Mit Hilfe eines TableRowSorters und eines eigens
* angepassten Comparators ist das kein Problem. Es können zwei Datums-Werte mit
* einander verglichen werden und somit kann auch festgestellt werden, welches
* Datum an welche Position gehört.
*
* @author Akeshihiro
* @version 1.0
*/
public class DateTableGUI extends JFrame {
/**
* Klassen-Versions-Kennung, die für die Serialisierung eine Rolle spielt.
*/
private static final long serialVersionUID = 1L;
/**
* Tabelle, die die Datums-Werte auflistet
*/
private JTable dateTable = null;
/**
* Erstellt das GUI.
*/
public DateTableGUI() {
/*
* ContentPane besorgen und in einer Container-Variable speichern. Dann
* kann man die Container-Variable nehmen anstatt
* this.getContentPane().<Operation>
*/
Container cp = this.getContentPane();
/*
* Layout der ContentPane setzen. Da es sich hierbei nur um ein Beispiel
* handelt, lohnt sich der Einsatz von GridBagLayout oder anderen eher
* komplexeren LayoutManagern nicht. Das FlowLayout gibt den Komponenten die
* passende Größe und positioniert sie von selbst nach einander und das
* reicht hierbei auch völlig aus.
*/
cp.setLayout(new FlowLayout());
// Die Tabelle für die Datums-Werte initialisieren.
getDateTable();
/*
* Da die Swing-Komponenten nicht selbstständig ScrollBars
* implementieren, braucht man für diesen Effekt eine ScrollPane, sonst
* kommt man nicht an die "nichtsichtbaren" Werte ran. Mit einer
* ScrollPane kann man zu diesen Werten scrollen und sie somit sichtbar
* machen.
*
* Diese ScrollPane beinhaltet die Datums-Tabelle und wird zur
* ContentPane hinzugefügt.
*/
JScrollPane sp = new JScrollPane(dateTable);
cp.add(sp);
/*
* Die benötigte Fenstergröße ermitteln und setzen lassen und zum
* Schluss das Fenster sichtbar machen lassen.
*/
this.pack();
this.setVisible(true);
}
/**
* Gibt die DatumsTabelle zurück. Sollte diese noch nicht initialisiert
* worden sein (null), dann wird sie initialisiert und entsprechend
* konfiguriert.<br>
* <br>
* Die Besonderheit besteht darin, dass die Tabelle die Werte nach dem Datum
* sortieren kann. Da dies keine StandardLösung bietet, muss der
* TableRowSorter ein neues Comparator-Objekt implementieren, das in der
* Lage ist zu erkennen, welches der zu vergleichenden Daten größer ist.
*
* @return DatumsTabelle
*/
public JTable getDateTable() {
// Prüfen, ob das DatumsTabellen-Objekt bereits initialisiert worden ist
if(dateTable == null) {
// Neue Tabelle erstellen
dateTable = new JTable();
// TableModel erstellen und mit Werten füllen
DefaultTableModel model = new DefaultTableModel(new String[][]{},
new String[]{"Datum"});
model.addRow(new String[]{"22.01.2009"});
model.addRow(new String[]{"21.02.2009"});
model.addRow(new String[]{"06.03.2009"});
model.addRow(new String[]{"22.05.1989"});
// TableRowSorter erstellen und ein neues Comparator-Objekt
// implementieren, um die DatumsWerte zu vergleichen
TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(
model);
rowSorter.setComparator(0, new Comparator<String>() {
public int compare(String o1, String o2) {
/*
* Einzelne Bestandteile rausholen (TT.MM.YYYY) Demnach
* entsteht ein Array mit folgendem Aufbau:
*
* ArrayXY[0] => Tag ArrayXY[1] => Monat ArrayXY[2] => Jahr
*/
String[] date1 = o1.trim().split("\\.");
String[] date2 = o2.trim().split("\\.");
// Calendar-Objekte von beiden Daten erstellen, um sie
// vergleichen zu können
Calendar cal1 = new GregorianCalendar(
Integer.parseInt(date1[2]),
Integer.parseInt(date1[1]),
Integer.parseInt(date1[0]));
Calendar cal2 = new GregorianCalendar(
Integer.parseInt(date2[2]),
Integer.parseInt(date2[1]),
Integer.parseInt(date2[0]));
/*
* Die Timestamps der beiden Daten vergleichen. Sind sie
* unterschiedlich, so wird geprüft, ob das erste Datum
* kleiner ist und somit vor dem zweiten Datum liegt. Der
* Rückgabewert wäre dann -1. Sollte der Timestamp des
* ersten Datums größer sein, als der des zweiten Datums, so
* ist der Rückgabewert +1. Sollten die Timestamps identisch
* sein, so wird 0 zurückgegeben und somit findet kein
* Tausch der Werte statt.
*/
if(cal1.getTimeInMillis() != cal2.getTimeInMillis()) {
return cal1.getTimeInMillis() < cal2.getTimeInMillis() ? -1 : 1;
}
return 0;
}
});
// Das TableModel in die Tabelle einsetzen
dateTable.setModel(model);
// Den TableRowSorter in die Tabelle einsetzen
dateTable.setRowSorter(rowSorter);
}
return dateTable;
}
}