JTable: Sortierproblem mit Renderer

stookie

Grünschnabel
Hallo zusammen,

ich arbeite an einem JTable, welche zwei Spalten mit Hilfe eines Renderers vergleicht und die Werte einer der beiden Spalten entsprechend einfärbt.
Nun habe ich den Sortieralgorithmus von Sun eingebunden und nach dem Sortieren stimmt die Färbung der Zellen nicht mehr. Zum Sortieren hab ich die Methode getColumnClass() vom DefaultTableModel überschrieben, damit Zahlen auch als solche erkannt und sortiert werden.

Interessant finde ich, dass ein anderer Renderer mit dem Sortieren keinerlei Probleme hat. Dieser Renderer führt aber auch keinen Vergleich zwischen zwei Spalten durch, sondern färbt nur negative Zahlen rot ein.

Hat jemand eine Idee, was ich wo und wie manipulieren muss, damit der Vergleich auch nach dem Sortieren wieder funktioniert? Wie gesagt, bevor ich sortiere, ist die Anzeige korrekt.

Danke schonmal

Katrin
 
stookie hat gesagt.:
Hallo zusammen,

ich arbeite an einem JTable, welche zwei Spalten mit Hilfe eines Renderers vergleicht und die Werte einer der beiden Spalten entsprechend einfärbt.
Nun habe ich den Sortieralgorithmus von Sun eingebunden und nach dem Sortieren stimmt die Färbung der Zellen nicht mehr.

Ohne Quellcode sind Tipps schwierig.

Zum Sortieren hab ich die Methode getColumnClass() vom DefaultTableModel überschrieben, damit Zahlen auch als solche erkannt und sortiert werden.

Ich persönlich empfehle prinzipiell das Arbeiten mit TableRows. Ich sollte wohl mal ein kleines Tutorial dazu verfassen...

Interessant finde ich, dass ein anderer Renderer mit dem Sortieren keinerlei Probleme hat. Dieser Renderer führt aber auch keinen Vergleich zwischen zwei Spalten durch, sondern färbt nur negative Zahlen rot ein.

Sollte normalerweise keinen Unterschied machen, aber ohne Code...

Hat jemand eine Idee, was ich wo und wie manipulieren muss, damit der Vergleich auch nach dem Sortieren wieder funktioniert? Wie gesagt, bevor ich sortiere, ist die Anzeige korrekt.

Danke schonmal

Katrin

Naja, je nachdem wie, was und wann Du sortierst.
 
Hallo nochmal,

ok, hab das Programm mal soweit gestutzt, dass ich den Quellcode posten kann.

Code:
  import javax.swing.*;
  import javax.swing.table.*;
  import java.awt.*;
  import java.awt.event.*;
  import java.util.*;
  import javax.swing.border.*;
  
  
  public class Sortieren extends JFrame 
  {
  	JScrollPane scrollPane = new JScrollPane();
  	  DefaultTableModel tableModel;
  	  
  	public static void main(String args[]) 
  	{
  		new Sortieren().show();
  	}
  	
  	
  	public Sortieren() 
  	{	
  		super("Test-GUI");
  		setSize(500,110);
  		
  		addWindowListener(new java.awt.event.WindowAdapter() {
 			public void windowClosing(java.awt.event.WindowEvent evt) {
  				exitForm(evt);
  			}
  		});
  		
  		tableModel = new DefaultTableModel() 
  		{
  			public Class getColumnClass(int columnIndex) 
  			{
  				switch (columnIndex) 
  				{
  				  case 0:
 					return Float.class;
  				  case 1:
 					return Float.class;
  				  case 2:
 					return Integer.class;
  				  default:
 					return null;
  				}	
  			}
  		};
  	
  		
  		TableSorter sorter = new TableSorter(tableModel);
 		JTable table = new JTable(sorter);		 
  		sorter.setTableHeader(table.getTableHeader());
  		
  		table.getTableHeader().setReorderingAllowed(false);
  		
  		tableModel.addColumn("Wert");
  		tableModel.addColumn("Referenz");
  		tableModel.addColumn("unwichtig");
  	   
  		
  		Vector zeile1 = new Vector();
  		zeile1.add(new Float(0.911));
  		zeile1.add(new Float(0.947));
  		zeile1.add(new Integer(56));
  		
  		Vector zeile2 = new Vector();
  		zeile2.add(new Float(0.824));
  		zeile2.add(new Float(1.010));
  		zeile2.add(new Integer(77));
  		
  		Vector zeile3 = new Vector();
  		zeile3.add(new Float(0.902));
  		zeile3.add(new Float(0.852));
  		zeile3.add(new Integer(7));
  		
  		Vector zeile4 = new Vector();
  		zeile4.add(new Float(1.155));
  		zeile4.add(new Float(1.273));
  		zeile4.add(new Integer(188));
  		
  		tableModel.addRow(zeile1);
  		tableModel.addRow(zeile2);
  		tableModel.addRow(zeile3);
  		tableModel.addRow(zeile4);
  		
  		table.getTableHeader().setReorderingAllowed(false);
  		   table.setEnabled(false);
  	  
  		scrollPane.setViewportView(table);
  
  		getContentPane().add(scrollPane, BorderLayout.CENTER);
  		
  		table.getColumnModel().getColumn(1).setCellRenderer(new VergleichRenderer());
  	}
  	 
  	
    
  	public class VergleichRenderer extends DefaultTableCellRenderer
  	{
 		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
  		{
 			Component renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
  			((JLabel)renderer).setOpaque(true);
  			
  			float ref = ((Float)value).floatValue();
 			float wert = ((Float)tableModel.getValueAt(row,column-1)).floatValue();
  			
  			if (ref > wert)
  			setBackground (Color.green);
  				
  			else 
  			setBackground (Color.yellow);
  				
  			return renderer;
  		}
  	} 
  	
  	
  	private void exitForm(java.awt.event.WindowEvent evt) 
  	{
  		System.exit(0);
  	}
  }

Ich hoffe mal, dass der Sortieralgo von Sun bekannt ist, ansonsten poste ich den Code auf Anfrage.

In dieser (kleineren) Tabelle wird falsch gerendert, wenn ich die erste Spalte per Klick auf den Spaltenkopf sortiere. Dies ist auch die Spalte, mit der im Renderer verglichen wird. Allerdings ist anzumerken, dass ich vorher noch zwei Spalten mit Strings in der Tabelle stehen hatte und beim Sortieren nach diesen Spalten wurde auch falsch gerendert.

Falls sich jemand das Problem erklären kann wäre ich dankbar, wenn derjenige es auch mir erklärt.

Bis dann

Katrin
 
Hallo Katrin,

Dein Problem liegt einfach daran, dass Du im Renderer das "Original"-TableModel benutzt und nicht das "Sorted"-TableModel.

Ich versuche das zu erklären. Die Klasse TableSorter ist nur ein Vermittler zwischen JTable und ihrem TableModel. Das heißt, es delegiert alle Events von der JTable an das TableModel und im Gegenzug holt die Daten von dem TableModel, sortiert sie und liefert dann an die JTable in sortierter Form. Daraus folgt, dass das eigentliche TableModel die Daten in unsortierter form vorliegen hat. Daher, wenn Du im Renderer versuchst, den Wert aus der ersten Spalte zu holen, bekommst Du ihn höchstwahrscheinlich aus einer falschen Zeile.

Die Lösung ist sehr einfach: ersetze diese Zeile:
Code:
float wert = ((Float)tableModel.getValueAt(row,column-1)).floatValue();
...durch die hier:
Code:
float wert = ((Float)table.getValueAt(row,column-1)).floatValue();
Gruß
Vincent
 

Neue Beiträge

Zurück