# Farbe einer einzelnen Zeile einer JTable ändern



## NdaG (8. Apr 2009)

Hi,

ich habe ein Problem mit einer JTable. Ich habe in jeder Zeile verschiedene Objekte und frage vor dem Speichern dieser Objekte in der Datenbank ab ob die Eingaben richtig sind. Falls diese es sind wird in der Datenbank gespeichert. Falls diese es jedoch nicht sind, so erscheint ein PopUp mit einer Fehlermeldung auf dem Bildschirm. Soweit so gut das funktioniert auch alles nun möchte ich aber dem Nutzer farblich kennzeichnen in welcher Zeile er Eingabefehler gemacht hat und genau da liegt mein Problem. Da es sich hier um verschiedene Objekte handelt die selbst keine setColor Funktion haben und leider auch keine Components sind finde ich einfach keine Lösung um die jeweilige Zeile farbig zu gestalten.

Danke im Voraus


----------



## Gast2 (8. Apr 2009)

http://www.java-forum.org/java-faq-beitraege/7032-jtable-teil-4-darstellung-der-daten.html


----------



## KindOfAutomatic (8. Apr 2009)

Hallo,

Du kannst deiner JTable einfach einen eigenen TableCellRenderer verpassen.
Erstelle einfach eine neue Klasse, lasse sie von DefaultTableCellRenderer erben und überschreibe die Methode
[highlight=java]public Component getTableCellRendererComponent(JTable table,
                                               Object value,
                                               boolean isSelected,
                                               boolean hasFocus,
                                               int row,
                                               int column)[/highlight]
Mit setBackground() bzw. mit setForeground() kannst du dann die Farbe der Zeile ändern.
Wie du siehst kannst du dort auch auf dein Objekt selbst zugreifen. Hinterlege in deinen Objektklassen einfach ein Flag, das du dann auf true setzt falls ein Fehler gemacht wurde.
In der getTableCellRendererComponent() Methode frägst du dieses Flag ab und änderst die Farbe entsprechend.

Vergiss nicht mit [highlight=java]JTable.setDefaultRenderer(Class columnClass, TableCellRenderer renderer)[/highlight] deiner JTable diesen Renderer auch zuzuweisen.

Dein TableCellRenderer könnte z.B. so aussehen : 
(sehr grob - hoffe ohne Fehler ( :  )

[highlight=java] public class MyTableCellRenderer extends DefaultTableCellRenderer {

@override
public Component getTableCellRendererComponent(JTable table,
                                               Object value,
                                               boolean isSelected,
                                               boolean hasFocus,
                                               int row,
                                               int column)
{

DeinObjekt obj = (DeinObjekt)value;


if(obj.getFlag()){

setBackground(Color.RED);

}

return this;

}


}


[/highlight]

EDIT: Da war wohl einer schneller ( :


----------



## André Uhres (8. Apr 2009)

NdaG hat gesagt.:


> Da es sich hier um verschiedene Objekte handelt die selbst keine setColor Funktion haben und leider auch keine Components sind finde ich einfach keine Lösung um die jeweilige Zeile farbig zu gestalten.


Was spricht dagegen, daß deine Objekte noch eine Schnittstelle "Colored" mit den Methoden "setColor" und "getColor" implementieren?
In JTable#prepareRenderer haben wir übrigens Zugriff auf sämtliche Renderer der JTable und können dort problemlos ganze Zeilen einfärben (Component#setBackground(Color c)).


----------



## NdaG (8. Apr 2009)

Ok super habs nun hinbekommen!

Danke an alle


----------



## mephistho (26. Mai 2009)

Hi, 

ich hab ein Problem mit einem CustomTableCellRenderer. Es geht um Schiffeversenken. Ich möchte je nach Wert der Zelle, eine Farbe darstellen lassen - später Schiffe zeichnen.

Ich setze den DefaultRenderer meiner Tabelle auf meinen selbsterstellten:

```
jEigenesFeld.setDefaultRenderer( Object.class , cellRenderer);
```

über meine Methode platziereSchiff(int startX, int startY, int endX, int endY) platziere ich die Schiffe, indem ich jeweils den Wert "s" eintragen lasse.


```
private void platziereSchiff(int startX, int startY, int endX, int endY) {
        if(startY == endY) {
            if(endX > startX) {
                for(int i = startX; i <= endX; i++) {
                    jEigenesFeld.setValueAt("s", startY, i);
                }
            }
            else if(endX < startX) {
                 for(int i = startX; i >= endX; i--) {
                    jEigenesFeld.setValueAt("s", startY, i);
                }
            }
        }
        else if(startX == endX) {
            if(endY > startY) {
                for(int i = startY; i <= endY; i++) {
                    jEigenesFeld.setValueAt("s", i, startX);
                }
            }
            else if(endY < startY) {
                 for(int i = startY; i >= endY; i--) {
                    jEigenesFeld.setValueAt("s", i, startX);
                }
            }
        }
    }
```

Und eiiigentlich sollte doch der folgende CustomTableCellRenderer nur die Zellen blau einfärben, in denen ein "s" steht, oder sehe ich das falsch?

```
public class CustomTableCellRenderer extends DefaultTableCellRenderer
{
    @Override
    public Component getTableCellRendererComponent
       (JTable table, Object value, boolean isSelected,
       boolean hasFocus, int row, int column)
    {
        Component cell = super.getTableCellRendererComponent
           (table, value, isSelected, hasFocus, row, column);
            try {
                if( value instanceof String ) {
                    
                    if(value.equals("s")) {
                        cell.setBackground( Color.BLUE );
                        //cell.setForeground(Color.BLUE);
                    }
                    else {
                        cell.setBackground( Color.WHITE );
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        return cell;
    }
}
```

Wie es tatsächlich läuft, sieht man hoffentlich auf den Screenshots.

Ich weiß nicht, was ich falsch mache. Vielleicht kann mir hier jemand weiterhelfen.

Danke & Gruß, 
meph


----------



## Michael... (26. Mai 2009)

mephistho hat gesagt.:


> ```
> public class CustomTableCellRenderer extends DefaultTableCellRenderer
> {
> @Override
> ...


Vermutlich liegt's an Zeile 11. Was soll passieren wenn value kein String ist. In dem Fall sollte ebenfalls ein Zustand definiert werden.


----------



## mephistho (26. Mai 2009)

BOAH! Danke!  Hätt ich auch selber mal probieren können.

Aber ist das nicht ein bisschen unsinnig? Er soll doch nur in den If-Block gehen, wenn eben ein String vorliegt. Wieso kann er dann überhaupt in irgendeinem anderen Fall auf dieselbe Idee kommen?


----------



## Michael... (26. Mai 2009)

Bin jetzt auch nicht der Experte darin.

Es liegt -glaube ich - an der Art der Tabellendarstellung. Für die Darstellung der Zellen wird die Abbildung einer Komponente genutzt (die der Rendererkomponente). D.h. pro Renderer exisitiert nur eine Komponente und diese wird entsprechend der Vorgaben im TableCellRenderer manipuliert. In deinem Fall ist der Hintergrund der Komponente irgendwann mal auf blau gesetzt worden. Bei den nächsten Zellen war value vermutlich null also instanceof String ergab false und an der Hintergrundfarbe wurde nichts geändert, also die blaue Hintergrundfarbe beibehalten.
In welcher Weise und Reihenfolge die Zellen einer Tabelle abgearbeitet werden ist mir allerdings noch unklar.


----------



## mephistho (26. Mai 2009)

Okay, stimmt, das macht Sinn.


----------



## André Uhres (27. Mai 2009)

Michael... hat gesagt.:


> In welcher Weise und Reihenfolge die Zellen einer Tabelle abgearbeitet werden ist mir allerdings noch unklar.


Wie das geschieht, ist für den Entwickler wohl unerheblich. Wir können uns den Renderer als konfigurierbaren Stempel vorstellen. Wenn ein bestimmtes Attribut, wie z.B. "background", zellenabhängig gesetzt werden soll, dann müssen wir sicherstellen, daß der "Stempel" auch immer für jeden einzelnen Fall passend konfiguriert wird. Meistens setzt man zuerst einen "default"-Wert, etwa cell.setBackground(table.getBackground()), ehe man die Abfragen für die speziellen Fälle macht.


----------

