JTable sortieren

Saban

Erfahrenes Mitglied
Hallo!

ich lass meine JTable mit der Zeile
Java:
tabelle.setAutoCreateRowSorter(true);
sortieren

Das Problem ist jetzt das mir das Datum falsch sortiert wird...

Beispiel:
01.01.09
01.02.09
06.01.09

kann mir da jemand weiterhelfen?

MfG
Saban
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

es wird so sortiert, weil nicht nach dem Datum-Wert sondern nach dem String sortiert wird und da kommt die 6 nach der 1. ;-)

Da wirst du nicht drum herum kommen, dir einen eigenen RowSorter zu schreiben.

Gruß

Sascha
 
Oder du drehst das Ausgabeformat um, also anstatt TT.MM.JJ machste JJ.MM, dann sollte es auch gehn. Allerdings würde ich dann das Jahr vierstellig anzeigen lassen, weil sonst weiß nacher niemand, was das soll.
 
Zuletzt bearbeitet:
Hi!

Danke erst mal für die Antworten! Der RowSorter klingt nach dem was ich gesucht habe. Ich habe es mir jetzt mal unter Java ist auch eine Insel angesehen.
Nur habe ich keine Ahnung wie ich des mit dem Datum da verwirklichen soll...
Hättest du mir da vllt nochmal nen Tip?

MfG
Saban
 
Dann musst du dir einen Comparator schreiben.
Die Klasse Date hat zwei Methoden(after, before) mit denen du prüfen kannst, ob ein Datum davor oder danach ist.


Gruß

Sascha
 
Um ein Datum zu vergleichen, könntest du dir ein Date oder Calendar Objekt erzeugen und dir daraus den entsprechenden Longwert holen und vergelcihen, oder du bringst das Datum in das Format JJJJMMDD und vergleichst es so anschließend.


//Edit
Ok, der Vorschlag von Sascha ist wohl etwas performanter ;)
 
Hallo,

Comparatorklasse bauen:

Code:
class DateStringComparator implements Comparator<String>
{
	public int compare(String strDate1, String strDate2) 
	{
		SimpleDateFormat dateFormat1 = new SimpleDateFormat("dd.MM.yyyy HH:mm");
		SimpleDateFormat dateFormat2 = new SimpleDateFormat("dd.MM.yyyy HH:mm");
		
		try 
		{
			if(strDate1 == null || strDate2 == null)
				return 0;
			
			if(strDate1.length() <= 11)
				dateFormat1 = new SimpleDateFormat("dd.MM.yyyy");
			
			if(strDate2.length() <= 11)
				dateFormat2 = new SimpleDateFormat("dd.MM.yyyy");
			
			Date date1 = dateFormat1.parse(strDate1);
			Date date2 = dateFormat2.parse(strDate2);
			
			return date1.compareTo(date2);
		}
		catch (ParseException e) 
		{
			e.printStackTrace();
		}
		
		return 0;
	}
}

und dann noch den Rowsorter setzen mit:
Code:
TableRowSorter oRowSorter = new TableRowSorter(TableModel);
table.setRowSorter(sorter);
oRowSorter.setComparator(iIndex, new DateStringComparator());

damit müsste es eigentlich klappen.

Grüße
R
 
Oha, gibt ja schon einige Vorschläge...

Naja, ich poste mal meinen Vorschlag trotzdem...

Java:
package datetable.gui;

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

import java.util.*;

public class DateTableGUI extends JFrame {
	private static final long serialVersionUID = 1L;

	private JTable dateTable = null;

	public DateTableGUI() {
		Container cp = this.getContentPane();
		cp.setLayout(new FlowLayout());

		getDateTable();
		JScrollPane sp = new JScrollPane(dateTable);
		cp.add(sp);

		this.pack();
		this.setVisible(true);
	}

	public JTable getDateTable() {
		if(dateTable == null) {
			dateTable = new JTable();

			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<TableModel> rowSorter = new TableRowSorter<TableModel>(
					model);
			rowSorter.setComparator(0, new Comparator<String>() {
				public int compare(String o1, String o2) {
					// Einzelne Bestandteile rausholen
					String[] date1 = o1.trim().split("\\.");
					String[] date2 = o2.trim().split("\\.");

					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]));
					if(cal1.getTimeInMillis() != cal2.getTimeInMillis()) {
						return cal1.getTimeInMillis() < cal2.getTimeInMillis() ? -1 : 1;
					}
					return 0;
				}

			});

			dateTable.setModel(model);
			dateTable.setRowSorter(rowSorter);
		}

		return dateTable;
	}
}
 
Hallo Zusammen!

erst mal danke für die zahlreichen Antworten!
@Ritchie_Fomm
ich verstehe bei dir nicht was die Zeile machen soll:
Java:
oRowSorter.setComparator(iIndex, new DateStringComparator());
und ob der Index hochgezählt werden soll oder wo der Index her kommt.
Des wäre auch sehr nett wenn du mir sagen könntest wo ich des am besten einbetten soll...

@Akeshihiro
bei der versteh ich den Code leider überhaupt nicht :( also was welcher Teil macht...

Könnt ihr mir des vllt noch erkären :) Danke im voraus!

MfG
Saban
 
Zuletzt bearbeitet von einem Moderator:
So, hier nochmal und diesmal sind an echt jeder Stelle Kommentare, teils auch sinnlose, aber ich weiß ja nicht, wie weit dein Verständnis reicht. Hoffe, dass du es diesmal besser verstehst.

Java:
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;
	}
}
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück