# TableCellRenderer



## jorgeHX (12. August 2004)

Also ich werde noch verrückt 

Alles was ich will, ist diesen doofen Renderer verstehen.

In meinem Programm nutze ich einen DefaultCellRenderer, also z.b.
myTable.setDefaultRenderer(Object.class, new ColoredTable());

In der Klasse ColoredTable will ich nun spezifisch festlegen, welche Zellen markiert sein sollen oder nicht.
Dazu lade ich aus meiner Datenbank alle Werte, die in der Tabelle mit einem grauen Kästchen hinterlegt sein sollen.

Mein Problem ist, dass dieser CellRenderer immer aufgerufen wird, sobald irgendwas an der Tabelle geschehen ist und dazu auch noch (row*column)mal.
Das ist ja super doof, da ich den Renderer ja eigentlich nur einmal zu Beginn brauche und dann wenn etwas neu eingefügt werden soll oder gelöscht werden soll.

Hat jemand vielleicht einen Tip, wie man einen individuellen CellRenderer anlegt und keinen DefaultCellRenderer? Ich finde einfach keine guten Links, die mir das erklären könnten.


----------



## Thomas Darimont (12. August 2004)

Hallo!

http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer
Schon versucht?

Gruß Tom


----------



## Snape (12. August 2004)

_Original geschrieben von jorgeHX _

>Alles was ich will, ist diesen doofen Renderer verstehen.

Ist doch ganz einfach: Ein Renderer dient zum Zeichnen bzw. zur Visualisierung von Komponenten. 

>Mein Problem ist, dass dieser CellRenderer immer aufgerufen wird, sobald irgendwas an der Tabelle geschehen ist und dazu auch noch (row*column)mal.

>Das ist ja super doof, da ich den Renderer ja eigentlich nur einmal zu Beginn brauche und dann wenn etwas neu eingefügt werden soll oder gelöscht werden soll.

Dagegen kannst Du nichts machen, das erledigt Java/Swing automatisch. Fensterwechsel, Datenänderungen und was weiss ich was noch alles auslöst, dass der Renderer (erneut) gezeichnet wird.

>Hat jemand vielleicht einen Tip, wie man einen individuellen CellRenderer anlegt und keinen DefaultCellRenderer? Ich finde einfach keine guten Links, die mir das erklären könnten.

Siehe Thomas' Link, auch ich habe einen guten Link (schau mal in die Linksammlung) für alles, was mit Tabellen zu tun hat.
Einen eigenen Renderer zu schreiben ist doch ganz einfach. Du musst lediglich Deiner Rendererklasse das Interface TableCellRenderer "spendieren" und damit die Methode

```
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
```
implementieren. Der DefaultTableCellRenderer ist ja eigentlich ein JLabel. Möchtest Du etwas anderes haben, dann leite entsprechend Deinen Renderer von der gewünschten Komponente ab, z.B.


```
class MyRenderer extends JButton implements TableCellRenderer
{
 Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) 
 {
   setText("Hallo Welt");
   return this;
 }
}
```

und dann in Deiner Klasse
myTable.setDefaultRenderer(Object.class, new MyRenderer());
setzen, das ist alles.

Du kannst natürlich auch für andere Klassen eigene Renderer setzen, z.B.

myTable.setDefaultRenderer(Integer.class, new MyRenderer());

Du musst dann allerdings im TableModel eine Methode getColumnClass implementieren, in der für jede Spalte die zugehörige Klasse zugewiesen wird.


----------



## jorgeHX (12. August 2004)

Vielen vielen Dank,
ich schau mir alles erstmal an


----------



## jorgeHX (12. August 2004)

*Re: Re: TableCellRenderer*



> *Original geschrieben von Snape
> 
> Dagegen kannst Du nichts machen, das erledigt Java/Swing automatisch. Fensterwechsel, Datenänderungen und was weiss ich was noch alles auslöst, dass der Renderer (erneut) gezeichnet wird.
> 
> *



Mmh, aber genau das kann man nicht verhindern? Immerhin wird ja immer ein JComponent zurückgeliefert und das belastet doch den GarbageCollector oder nicht?
Bei mir würde das ja bedeuteten, dass bei jedem Fensterwechsel etc. die Daten aus der Datenbank immerwieder aufs Neue mit der Tabelle verglichen werden und bei Übereinstimmung erneut das farbliche Label gezeichnet wird. Ist das nicht ineffizient? Oder gibt es dafür keine andere Lösung?

Die Linksammlung ist sehr cool. Hatte ich noch gar nicht gesehen. Danke


----------



## jorgeHX (12. August 2004)

Erstmal Danke für eure ununterbrochene Hilfe. Immerhin helft ihr mir schon seit geraumer Zeit.... 
Ich hoffe ihr seit nicht sauer wenn ich oft poste.

Die Links etc. waren hilfreich, allerdings stoße ich immerwieder auf Probleme, die wohl einfach zu lösen sind, wenn man das nötige Know-how hat.

1. Kann man in einer JTable die 7*7 groß ist, es so einstellen, dass bestimmte Zellen nicht selektierbar sind?

2. Kann man in einer JTable nur eine horizontale Linie haben? ich habe mit setShowGrid alles verschwinden lassen, aber eine Zeile sollte unterstrichen sein?

3. Kann man nur mit den Pfeiltasten der Tastatur von einer JTable in eine Andere springen, wenn man am Ende der Ersten angelangt ist? 

Ich bin ich neu im Umgang mit JTables daher diese drei Fragen...
Sorry


----------



## Snape (12. August 2004)

_Original geschrieben von jorgeHX _

>1. Kann man in einer JTable die 7*7 groß ist, es so einstellen, dass bestimmte Zellen nicht selektierbar sind?

Nicht selektierbar? Hm, gute Frage, k.A. Reicht nicht editierbar auch?

>2. Kann man in einer JTable nur eine horizontale Linie haben? ich habe mit setShowGrid alles verschwinden lassen, aber eine Zeile sollte unterstrichen sein?

Sollte mit dem TableCellRenderer möglich sein, oder?

>3. Kann man nur mit den Pfeiltasten der Tastatur von einer JTable in eine Andere springen, wenn man am Ende der Ersten angelangt ist? 

Ui, noch so eine Spezialfrage... k.A., aber ich denke das geht über KeyEvents.
Der Tabelle einen KeyListener zufügen und bei -> prüfen, ob die letzte Spalte (oder Zeile, je nachdem was Du möchtest) markiert ist, wenn ja: ab in die nächste Tabelle.

>Ich bin ich neu im Umgang mit JTables daher diese drei Fragen...

Auch wenn man schon ein alter Hase ist, sind das durchaus interessante Fragen. 

>Sorry 

Brauchst Dich doch nicht zu entschuldigen für Fragen.


----------



## Snape (12. August 2004)

*Re: Re: Re: TableCellRenderer*

_Original geschrieben von jorgeHX _
>Mmh, aber genau das kann man nicht verhindern? Immerhin wird ja immer ein JComponent zurückgeliefert und das belastet doch den GarbageCollector oder nicht?

Wieso?

>Bei mir würde das ja bedeuteten, dass bei jedem Fensterwechsel etc. die Daten aus der Datenbank immerwieder aufs Neue mit der Tabelle verglichen werden

Dann hast Du m.E. einen Designfehler in Deinem Programm. Bei Fensterwechsel Daten aus der Datenbank neu laden hört sich ziemlich performancelastig an.

>und bei Übereinstimmung erneut das farbliche Label gezeichnet wird. Ist das nicht ineffizient?

Es wird so oft neu gezeichnet, und wohl aus gutem Grund. Ineffizienz sehe ich noch nicht, der Renderer wird ja nur einmal erzeugt und danach lediglich eine Referenz zurückgegeben.

>Oder gibt es dafür keine andere Lösung?

Ich würde einfach das Daten einlesen cleverer steuern. Nur dort, wo es wirklich nötig ist.

>Die Linksammlung ist sehr cool. Hatte ich noch gar nicht gesehen. Danke 

Irre, was man mit/in Tabellen alles zaubern kann, gell?


----------



## jorgeHX (12. August 2004)

Da bin ich ja froh  

Also nicht-editierbar reicht nicht. Ich möchte, dass bestimmte Zellen nur sichtbar aber nicht klickbar sind.... Weißt du das was?

Außerdem check ich nicht, wie man in einem JTable in die drunter-oder drüberliegende Reihe gelangt, wenn man nur die Pfeiltasten LINKS und RECHTS benutzt. Bei mir stoppt er immer am Ende der Reihe.... Hilfe  

Den Rest versuch ich jetzt mal... Danke


----------



## Snape (12. August 2004)

_Original geschrieben von jorgeHX _

>Also nicht-editierbar reicht nicht. Ich möchte, dass bestimmte Zellen nur sichtbar aber nicht klickbar sind.... Weißt du das was?

Sorry, da muss ich passen. Würd mich auch mal interessieren, ob und wenn ja wie das geht.

>Außerdem check ich nicht, wie man in einem JTable in die drunter-oder drüberliegende Reihe gelangt, wenn man nur die Pfeiltasten LINKS und RECHTS benutzt. Bei mir stoppt er immer am Ende der Reihe.... Hilfe  

Hehe, stimmt natürlich... 
Wilst Du denn am Ende der ersten Zeile mit der -> in die erste Zelle der zweiten Zeile gelangen usw.? Oder was genau schwebt Dir vor?
Auf jeden Fall wirst Du vermutlich nicht drum herumkommen, Dich mit einem KeyListener auseinanderzusetzen.


----------



## jorgeHX (12. August 2004)

Wenn ich was herausgefunden habe, poste ich es hier....

Das mit dem Pfeil --> hast du richtig zusammengefasst. Ich will dann eine Zeile tiefer.
Dann muss ich mir wohl den KeyListener mal anschauen.


----------



## jorgeHX (15. August 2004)

Moin Snape,
ich denke es interessiert dich wie ich meine Probleme gelöst habe, daher poste ich mal meine Lösung...

Das Problem mit nicht klickbar habe ich mit einem Überschreiben der Methode changeSelection(..) gelöst. In etwa so....

```
...
MyTable table = new MyTable();
...
class MyTable extends JTable {   
   public void changeSelection(int row, int column, boolean toggle, boolean extend){    
     if (getValueAt(row, column)==null || row == 0) {        
            return;     
     }     
      else {       
             super.changeSelection(row, column, toggle, extend);     
      }   
   }  
}
```

Das Problem mit dem Pfeil habe ich durch Überschreiben der Key-Eigenschaft von Arrow-Right und Arrow-Left gelöst. In etwa so....


```
InputMap im = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
//  Have the RIGHT key work the same as the tab key     
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);     
KeyStroke arrowPlus = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);     
im.put(arrowPlus, im.get(tab));     
//  Have the LEFT key work the same as the shift+tab key     
KeyStroke shiftTab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_MASK );     
KeyStroke arrowMinus = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); 
im.put(arrowMinus, im.get(shiftTab));
```

Somit hat kein Zweiter mehr dasselbe Problem   Ich hab lang genug gebraucht...


----------

