komplexes JTable Renderer Problem

McSnoop

Grünschnabel
Farben:

selected
normal
focused

Spalten:

Boolean|Boolean|Integer|String|Integer|Integer|Double|Integer|Integer

alle Boolwerte werden als Checkbox dargestellt.

nun gehn die Probleme los. die Renderer die ich bis jetzt geschrieben habe die funzten nur so das sie entweder alle zellen zu Strings machten oder halt nur auf die spalte die Strings enthalten angewendet wurden.

Selectiert werden kann immer nur 1 Zeile.

Ich möchte den Renderer so hinbekommen das auf alle Zellen die Farben oben angewendet werden ohne das er den Zellentyp verändert. Sprich wenn dort vorher eine Checkbox drinnen war soll danach auch wieder eine checkbox drinnen sein.

Es hat noch kein Renderer richtig geklappt. =( Leider.

PS:

mein bisheriger Renderer:

Code:
public class Renderer extends JLabel implements DefaultTableCellRenderer{
private Color colorSelected = new Color(200,255,200);
private Color colorFocus = new Color(255,200,200);
private Color colorNormal = new Color(200,200,255);
 
public Renderer(){
setOpaque(true);
}
 
 
public Component getTableCellRendererComponent( ... normale Parameterliste){
	if(hasFocus)
	 setBackground(colorFocus);
else if(isSelected)
	 setBackgroun(colorSelected);
	else
	 setBackground(colorNormal);
 
if(value instanceof Boolean){
	 boolean enabled = ((Boolean)value).booleanValue();
	 final JCheckBox box = new JCheckBox();
	 box.setHorizontalAlignment(SwingContants.CENTER); 
	 box.setSelected(enabled);
	 return box;
	}
 
	 if(value instanceof Double){
	 final JLabel label = new JLable();
	 label.setHorizontalAlignment(SwingContants.CENTER); 
	 label.setText(value.toString());	<-----
	 return label;
	 }
 
	if(value instanceof Integer){
	 final JLabel label = new JLable();
	 label.setHorizontalAlignment(SwingContants.CENTER); 
	 label.setText(value.toString());	<-----
	 return label;
	 }
 
return this;
}
 
}

meine modelspezifikationen:

Code:
public Class getColumnClass(int c){
return getClass();
}

ich habe auch eine variante von getColumnClass in der ich einen Spaltefestgelegten return gebe, aber da passiert nichts anderes.

Fragen:

1. Warum werden die Farben nicht auf die CheckBox angewandt

Ausserdem wird der Renderer zwar auf alle anderen Spalten angewandt, aber nur vom
value.toString() her. Die Farben werden nicht gesetzt bei allen Zellen wo vorher kein
String drinnen war.

2. Warum kommt wenn ich dann bei der CheckBox den Haken setzen will der Boolwert
der dahinter steht und nicht der Haken der eigentlich kommen sollte

3. Gibt es die Möglichkeit statt

value.toString();

den Inhalt der Zelle anders zurückzugeben so das der Typ erhalten bleibt

bin für jede Erklärung/Tip/Hilfe dankbar.

mfg
Snoop
 
Zuletzt bearbeitet:
N'Abend,
also mit den TableCellRenderern funktioniert das so:
Man kann für jede Klasse einen eigenen (!) Renderer hinterlegen. Dieser muss lediglich von JComponent abgeleitet sein - oder von einer direkt von JComponent abgeleiteten Klasse wie JLabel, JTextField usw., weiß ich jetzt nicht genau.
Damit ergibt sich die Notwendigkeit, im TableModel die Klassen für jede einzelne Spalte geeignet zu wählen, also genau zu überlegen, wie die Implementierung von getColumnClass(...) auszusehen hat. Berücksichtigt werden muss dabei natürlich, dass für jede Spalte des gleichen Typs der gleiche Renderer gilt. Wenn also 5 Spalten Integer sind und der Renderer gesetzt wird auf (Integer.class, myIntegerRenderer), dann wird dieser Renderer auf alle 5 Integer Spalten angewendet. Sollen aber nur 4 der 5 Integer-Spalten diesen einen Renderer erhalten und der 5. einen anderen, so ist dieser Spalte eine andere Klasse zuzuweisen. Notfalls muss man sich eine eigene Klasse kurz zusammen basteln.

Ich habe mir Deinen Code nicht genauer angeschaut, sehe aber, dass Du vom DefaultTableCellRenderer erbst. Das kann mitunter gar nicht gut sein, denn der DefaultTableCellRenderer ist nichts anderes als ein JLabel afaik. Alternativ kannst Du z.B. direkt von JButton erben, Du musst lediglich das Interface TableCellRenderer implementieren, also nur die Methode getTableCellRendererComponent(...).

FYI: Wer noch nie einen eigenen Renderer geschrieben hat und trotzdem problemlos mit Tabellen und auch der ColumnClass hantierte, wird sich evtl. wundern, weshalb das so einfach ging. Das liegt daran, dass für bestimmte Klassen intern per default ein TableCellRenderer hinterlegt wurde. Für den Typ Boolean zeigt die Tabelle eine CheckBox an, für Strings ein JLabel usw.

Das nur mal so zur Funktionsweise des Renderers. Ähnlich funktioniert übrigens auch der Editor.

Ich hoffe, das hilft Dir entweder direkt bei Deinem Problem oder vielleicht indirekt, weil Du evtl feststellst, dass Dein Konzept umgestellt werden sollte/muss.
 
ups habe vergessen "JLabel implements" dazwischen zu schreiben.

die Funktionsweise des Renderers ist mir soweit bekannt.

Aber wieso kann ich nicht einfach das in die zelle zurückgeben was vorher in der Zelle drinnen stand und ich meine jetzt nicht den Wert sondern einfach alles, also Typ + Inhalt. Weil das ist ja das Problem, er macht alles zu Strings, Double Int usw.

wenn JLabel nur Strings darstellt, was muss ich nehmen damit er halt components an sich darstellt
 
McSnoop hat gesagt.:
ups habe vergessen "JLabel implements" dazwischen zu schreiben.

die Funktionsweise des Renderers ist mir soweit bekannt.

Aber wieso kann ich nicht einfach das in die zelle zurückgeben was vorher in der Zelle drinnen stand und ich meine jetzt nicht den Wert sondern einfach alles, also Typ + Inhalt. Weil das ist ja das Problem, er macht alles zu Strings, Double Int usw.

wenn JLabel nur Strings darstellt, was muss ich nehmen damit er halt components an sich darstellt

Moin,
gib einfach die gewünschte Komponente zurück. Wenn es eine CheckBox sein soll, dann eben return new JCheckBox() usw.
 
ja mit der checkbox besteht jetzt nur noch das problem das wenn ich sie zurück gegbeen habe zwar sehe aber wenn ich drauf klicke kommt der äqivalente String und ich komm nicht mehr raus aus der zelle.

als was würdest du einen Double bzw Integer zurück geben so das der Typ in der Zelle erhalten bleibt

Wenn ich die als Label zurückgebe wirds nen String. =(
 
Moin,
na ich würde einen Double oder Integer auch als JLabel zurückgeben, als Boolean/JCheckBox ergibt es keinen Sinn. Der Typ wird ja durch den Renderer nicht verändert. Dafür ist das set/getValueAt(...) zuständig.
 
wenn du aber Double oder Integer als JLabel zurückgibts musst du doch auch im renderer sagen

Code:
if(value instanceof Integer){
  setText(to.String());
  return this;
}

durch das to.String() machst du doch automatisch nen String draus oder nicht?
 
das problem ist das er wenn er nen string draus macht ich nichts mehr eingeben kann.

die Spalte in der Double werte reinsollen steht nun ein String und wenn ich da nen Double eingebe dann macht er die zelle rot und läßt mich nicht mehr raus, weil ich es so definiert habe das man nur Double eingeben kann.

vielleicht reden wir auch aneinander vorbei, kannst du evtl mal ein beispiel geben wie du:

den renderer und set/getValueAt(...) schreibst

so sieht mein setValueAt aus. Für jede Spalte gibt entsprechend einen anderen Typ.

Code:
im Table Model
 
public void setValueAt(Object value, int row, int col){
  try{
	switch (col){
	  case 0:  {
				   data[row][col]=(Boolean)value;
				   fireTableCellUpdated(row,col);
				   }
	  case 1:  {
				   data[row][col]=(Boolean)value;
				   fireTableCellUpdated(row,col);
				   }
	  case 2:  {
				   data[row][col]=(Integer)value;
				   fireTableCellUpdated(row,col);
				   }
 
	usw.
 
 
	}
  }
  catch(...){}
}

mein getValueAt sieht folgendermaßen aus:

Code:
public Object getValueAt(int row, int col){
   return data[row][col];
}
 
McSnoop hat gesagt.:
ja mit der checkbox besteht jetzt nur noch das problem das wenn ich sie zurück gegbeen habe zwar sehe aber wenn ich drauf klicke kommt der äqivalente String und ich komm nicht mehr raus aus der zelle.

als was würdest du einen Double bzw Integer zurück geben so das der Typ in der Zelle erhalten bleibt

Wenn ich die als Label zurückgebe wirds nen String. =(
Hi,
ich würde mal denken, dass wenn Du darauf klickst das nicht mehr sache des Renderers
sondern des Editors ist.
Ich selbst habe was Renderer und Editoren angeht ziemlich alle vom Default abgeleitet, allerdings musste ich dafür auch ne Menge Sourcecode lesen und halbwegs kaperien, um die Defaults gescheit verändern zu können.

Takidoso
 
Zurück