JTable Sortieren - Spalte mit Calendar Typ sortiert nicht korrekt

DarthShader

Erfahrenes Mitglied
Hallo,

ich versuche, eine JTable zu sortieren. Ich habe eine Spalte, welche die Zeit darstellt - der Typ dieser Spalte ist "Calendar". Ich habe nun einen TableRowSorter erstellt mit dem entsprechenden SortKey für die Spalte.

In der Dokumentation [1] steht, dass beim Sortieren geschaut wird, ob das Objekt der Spalte ein compareable ist - was Calendar ja ist. Ich kann also 2 Calendar Objekte über .compareTo miteinander vergleichen, was auch funktioniert.

Nur in der Tabelle funktioniert es nicht: die Zeitwerte werden nicht korrekt sortiert, und ich erkenne irgendwie kein Muster, wann es korrekt ist und wann nicht. Ein Beispiel:

1. 10.11.2008 10:15
2. 10.11.2008 10:22

So liegt das 2. Datum klar nach dem ersten, es ist also später. Die Tabelle sortiert dies auch korrekt, d.h. die Zeile mit der Zeit "10:22" ist unter der Zeile mit der Zeit "10:15".

Aber bei folgenden Zeiten:

1. 10.11.2008 10:15
2. 10.11.1999 10:22

Hier ist das 2. Datum VOR dem 1., da es ja im Jahre 1999 liegt (1999 liegt zeitlich vor 2008). Meine Tabelle kappiert das aber einfach nicht, und sortiert es so, dass wieder das 2. Datum unter der Zeile mit dem 1. Datum ist, was definitiv falsch ist.

Wenn ich ein paar Daten in die Tabelle eintrage, so sieht es danach so aus:

1. 22.05.2008 15:54
2. 22.05.2008 15:57
3. 22.05.1007 15:58
4. 22.05.1006 15:56
5. 22.05.1999 16:00


Wie kommt denn nur diese Sortierung zu Stande? Ich meine, Zeile 1 und 2 sind ja korrekt, aber die folgenden Zeilen 3, 4 und 5 sollten doch alle vor 1 und 2 liegen - warum werden die nach unten sortiert?

Ich weiß, ich habe jetzt keinen Code gepostet. Dieser ist nicht so klein, falls das aber hilfreich ist, mache ich das natürlich noch. Ich glaube momentan fast nicht, dass es am Code liegt, da die Sortierung mit anderen Spalten ja funktioniert (z.B. mit Strings), nur beim Calendar gibt es so merkwürdige Probleme. Vielleicht hat ja jemand schonmal Calendar Objekt in einer Tabelle benutzt und danach sortiert.


Über Hilfe würde ich mich sehr freuen, ich bin hier halb am verzweifeln...


Vielen Dank!


[1] http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#sorting
 
Hallo,

wie es aussieht, werden die Daten nur nach Uhrzeit sortiert, das Datum wird ignoriert. Probier doch einfach die Daten auf der Long-Basis zu sortieren. Über Caledar.getTimeInMillis() bekommst du ja die Long-Repräsentation von dem Caledar Objekt. Die Sortierung sollten dann stimmen.

Grüße
Vincent
 
Ich benutze ja einen TableRowSorter, um zu sortieren. Dem habe ich auch schon einen eigenen Comparator für meine Zeit-Spalte gegeben, der genau das tut, also die Calendar Objekte nach ihrem long Wert sortieren. Leider wurde der Comparator nie aufgerufen, d.h. die JTable kam gar nicht dazu, den entsprechenden Comparator zu benutzen, und hat die Spalte stattdessen irgendwie anders sortiert (vielleicht hat er die einfache String repräsentation sortiert?)

Aber das ist ein anderes Thema, dafür würde ich auch noch etwas Beispielcode hier rein posten.

Kurz zu Deiner Antwort: im letzten Beispiel ist die 4. Zeit "22.05.1006 15:56", wenn tatsächlich nur nach Uhrzeit sortiert würde, dann müsste das doch an 2. Stelle stehen, also nach "15:54" und vor "15:57".

Ich kappiers einfach nicht. Habe gestern noch stundenlang alles ausprobiert, ich kriege ihn einfach nicht zum korrekten sortieren - ich denke ich werde die Problematik mal in ein vereinfachtes Beispielprogramm pcaken, damit wir besser darüber reden können bzw. der Fehler auch mal reproduziert werden kann :)
 
Hallo,

ich komme dem Problem nicht auf die Schliche - deshalb habe ich nun den entsprechenden Code mal aus meinem Programm extrahiert, damit nur das Nötigste drin steht. Der folgende Code macht eigentlich nichts anderes, als ein Fenster erstellen, eine Tabelle mit 3 Spakten erstellen, der Tabelle ein paar Einträge hinzufügen und dann zu versuchen, diese nach der 2. Spalte (der Zeit) zu sortieren:

Java:
import java.awt.Component;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.swing.*;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.*;

public class TableSortingTest
{
	@SuppressWarnings( "serial" )
	private class MyTableCellRenderer extends DefaultTableCellRenderer
	{
		@Override
		public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column )
		{
			JLabel c = (JLabel)super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );

			if ( value instanceof Calendar )
			{
				SimpleDateFormat df = new SimpleDateFormat( "dd.MM.yyyy HH:mm" );
				c.setText( df.format( ( (Calendar)value ).getTime() ) );
			}

			return c;
		}
	};

	private static final int	COLUMN_DATA		= 0;
	private static final int	COLUMN_TIME		= 1;
	private static final int	COLUMN_VALUE	= 2;
	
	public TableSortingTest()
	{
		// Create window
		JFrame frame = new JFrame( "Table Sorting Test" );
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setSize( 640, 480 );
		frame.setLocationRelativeTo( null );

		// Create table component
		JTable table = new JTable();
		table.setDefaultRenderer( Object.class, new MyTableCellRenderer() );

		DefaultTableModel model = new DefaultTableModel( 0, 3 );
		table.setModel( model );

		TableColumnModel columnModel = table.getColumnModel();
		columnModel.getColumn( COLUMN_DATA ).setHeaderValue( "Data" );
		columnModel.getColumn( COLUMN_TIME ).setHeaderValue( "Zeit" );
		columnModel.getColumn( COLUMN_VALUE ).setHeaderValue( "Wert" );

		// Create calendar objects for the time column
		Calendar time1 = Calendar.getInstance();
		Calendar time2 = Calendar.getInstance();
		Calendar time3 = Calendar.getInstance();
		Calendar time4 = Calendar.getInstance();
		Calendar time5 = Calendar.getInstance();

		// Set different times
		time1.set( 2008, 4, 22, 15, 54);
		time2.set( 2008, 4, 22, 15, 57);
		time3.set( 1007, 4, 22, 15, 58);
		time4.set( 1006, 4, 22, 15, 56);
		time5.set( 1999, 4, 22, 16, 00);
		
		// Add rows to the table model
		model.addRow( new Object[] { null, time1, "Zeit 1" } );
		model.addRow( new Object[] { null, time2, "Zeit 2" } );
		model.addRow( new Object[] { null, time3, "Zeit 3" } );
		model.addRow( new Object[] { null, time4, "Zeit 4" } );
		model.addRow( new Object[] { null, time5, "Zeit 5" } );
		
		// Create table row sorter
		TableRowSorter< TableModel > sorter = new TableRowSorter< TableModel >( table.getModel() );
		sorter.setSortsOnUpdates( true );

		// Create the sort keys
		List< SortKey > sortKeys = new ArrayList< SortKey >();
		sortKeys.add( new SortKey( COLUMN_TIME, SortOrder.ASCENDING ) );

		sorter.setSortKeys( sortKeys );
		table.setRowSorter( sorter );

		frame.add( table );
		frame.setVisible( true );
	}

	public static void main( String[] args )
	{
		new TableSortingTest();
	}

}

(Das Programm sollte so lauffähig sein - einfach in eine entsprechende Java Datei kopieren, kompilieren und starten)

Das merkwürdige ist, dass die Sortierung nach dem Start des Programmes korrekt ist. Macht man aber ein Doppelklick in eine Zelle der 1. Spalte und trägt irgendwas ein, z.B. "123", so verändert sich die Sortierung plötzlich. Trägt man nacheinander in allen Zellen der 1. Spalte was ein, so endet die "Sortierung" so, dass nichts mehr sortiert ist.

Ich würde mich wirklich freuen, wenn mich jemand mal über dieses Verhalten der Tabelle aufklären könnte. Denn das wird auch die Antwort darauf sein, warum die Sortierung in meinem richtigen Programm zu falsch läuft.

Vielen Dank für Eure Hilfe!
 
Zurück