# im JTable die Schriftfarbe ändern



## pappender (31. Mrz 2016)

Hallo,

wie kann man die Schriftfarbe von Zellen ändern, wenn z. B. ein bestimmter Wert in einer Zelle steht.

```
public class MyRenderer extends JLabel implements TableCellRenderer {
        private static final long serialVersionUID = 739847213311575670L;

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
                boolean hasFocus, int row, int column) {
                       
            setForeground(Color.BLACK);
            if(value == "xxx"){
                setForeground(Color.RED);
            }
            return this;
        }
    }
```

Also mit setForeground(Color.BLACK); stelle ich alles auf schwarz und wenn in einer Zelle 'xxx' steht, soll sich die Schriftfarbe auf rot ändern.
Aber irgendwie bekomme ich es nicht hin.


----------



## Flown (31. Mrz 2016)

Strings vergleicht man mit `equals` und nicht mit `==`


----------



## pappender (31. Mrz 2016)

Danke für den Hinweis.
Ich habe den Code nochmal geändert:

```
public class MyRenderer extends JLabel implements TableCellRenderer {
        private static final long serialVersionUID = 739847213311575670L;

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
           
            String s = value.toString();
            if(s.equals("xxx")){
                setForeground(Color.RED);
            }else{
                setForeground(Color.BLACK);
            }
            setText(s);
            return this;
        }
    }
```

Jetzt wird mir aber ein Fehler ausgespuckt und das Programmfenster ist schwarz.


----------



## Java20134 (31. Mrz 2016)

Könntest du die Fehlermeldung posten?


----------



## pappender (31. Mrz 2016)

Es geht wohl um folgende Meldung: java.lang.NullPointerException


----------



## Java20134 (31. Mrz 2016)

Na dann überprüfe in der Methode oder davor, welches Objekt oder Variable null ist und dann schaue weiter!


----------



## pappender (31. Mrz 2016)

Ich denke ich habe das Objekt gefunden.

Ich rufe mit
tablePlanung.setDefaultRenderer(Object.class, new MyRenderer());
folgende Methode auf:

```
public class MyRenderer extends JLabel implements TableCellRenderer {
        private static final long serialVersionUID = 739847213311575670L;

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
         
            if(value.equals("xxx")){
                setForeground(Color.RED);
            }else{
                setForeground(Color.BLACK);
            }
            return this;
        }
    }
```

Es muss an das value liegen: if(value.equals("xxx")){
Aber ich verstehe nicht warum.


----------



## Schesam (1. Apr 2016)

ZEig doch mal den kompletten StackTrace (Die komplette Fehlermeldung). Aber wenn value null ist, dann ist in der Zelle nix drin


----------



## pappender (1. Apr 2016)

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at org.ids.xxx.MainIDS$MyTableCellRenderer.getTableCellRendererComponent(MainIDS.java:274)
    at javax.swing.JTable.prepareRenderer(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
    at javax.swing.plaf.ComponentUI.update(Unknown Source)
    at javax.swing.JComponent.paintComponent(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JViewport.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JLayeredPane.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    at java.awt.Container.paint(Unknown Source)
    at java.awt.Window.paint(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1200(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)


----------



## pappender (1. Apr 2016)

Ich habe den Code nochmal geändert und Beispielsweise mit 'hasFocus' probiert.

```
private class MyTableCellRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = -8993881568812935223L;

        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            JLabel l = new JLabel((String)value);
            l.setOpaque(true);
            l.setFont(table.getFont());
            l.setForeground(table.getForeground());
            l.setBackground(table.getBackground());
           
            if (hasFocus) {
                l.setForeground(Color.RED);
            }else{
                l.setForeground(Color.BLACK);
            }
           
            return l;
           
        }
    }
```
Das funktioniert.
Sobald ich aber wieder auf einen bestimmten String prüfen möchte: if(value.equals("xxx")){, dann gehts nicht. Es kommt zwar keine Fehlermeldung, aber die Textfarbe wird nicht geändert.


----------



## pappender (1. Apr 2016)

Ich habe es. Ich habe equals falsch eingesetzt.
So ist es richtig:


```
private class MyTableCellRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = -8993881568812935223L;

        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            JLabel l = new JLabel((String)value);
            l.setOpaque(true);
            l.setFont(table.getFont());
            l.setForeground(table.getForeground());
            l.setBackground(table.getBackground());
          
            if ("xxx".equals(value)) {
                l.setForeground(Color.RED);
            }else{
                l.setForeground(Color.BLACK);
            }
          
            return l;
          
        }
    }
```


----------



## pappender (1. Apr 2016)

Eine Geschichte hätte ich dann doch noch.
Wie kann man auf ein Teilstring prüfen. Also mit contains wahrscheinlich.
Aber wie setze ich eqals und contains zusammen?


----------



## Thallius (1. Apr 2016)

pappender hat gesagt.:


> Ich habe es.



Ganz sicher nicht. Ob Du "xxx".equals(value) oder value.equals("xxx") schreibst ist sowas von egal.


----------



## pappender (1. Apr 2016)

Hm, also bei mir nicht.
Wenn ich

```
if (value.equals("xxx")) {
                l.setForeground(Color.RED);
            }else{
                l.setForeground(Color.BLACK);
            }
```
 nutze, dann wird mir der o. g. Fehler angezeigt.

So gehts aber:

```
if ("xxx".equals(value)) {
                l.setForeground(Color.RED);
            }else{
                l.setForeground(Color.BLACK);
            }
```




Auf Teilstring prüfen, habe ich jetzt auch hinbekommen:

```
if (value instanceof String) {
                String s = (String)value;
                if (s.contains("xxx")) {
                    l.setForeground(Color.BLUE);
                }else if (s.contains("yyy")) {
                    Color cGreen = new Color(0,176,80);
                    l.setForeground(cGreen);
                }
            }
```


----------



## InfectedBytes (1. Apr 2016)

Thallius hat gesagt.:


> Ganz sicher nicht. Ob Du "xxx".equals(value) oder value.equals("xxx") schreibst ist sowas von egal.


Nicht ganz, in den meisten Fällen macht es zwar keinen Unterschied, jedoch kann value auch null sein und somit zu anderem Verhalten führen:

```
value.equals("xxx"); // wirft exception falls value null ist
"xxx".equals(value); // wirft keine exception falls value null ist
```
Aber dies ist eben nur ein einziger Fall in dem es sich anders verhält, im allgemeinen macht es wie schon erwähnt keinen Unterschied.


----------



## Thallius (1. Apr 2016)

InfectedBytes hat gesagt.:


> Nicht ganz, in den meisten Fällen macht es zwar keinen Unterschied, jedoch kann value auch null sein und somit zu anderem Verhalten führen:
> 
> ```
> value.equals("xxx"); // wirft exception falls value null ist
> ...



Weswegen ich immer erstere Variante benutze. Denn wenn Value null ist, sollte ich das abfangen und nicht der Compiler. Im ersten Fall werde ich auf meinen Fehler aufmerksam gemacht im zweiten kann es sonst später zu sehr schwer ermittelbaren Fehlern kommen.

Gruß

Claus


----------



## pappender (1. Apr 2016)

Okay, danke @Thallius, werde ich in Zukunft berücksichtigen.


Nochmal eine andere Frage.
Umso mehr in die Methode für ein individuelles Design geschrieben wird, umso langsamer ist das ganze Programm, oder? Die Darstellung stottert, wenn man zum Beispiel scrollt.


Oder ist der DefaultTableCellRenderer falsch aufgebaut?

```
private class MyTableCellRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = -8993881568812935223L;

        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
          
          
          
            JLabel l = new JLabel((String)value);
            l.setOpaque(true);
            l.setFont(table.getFont());
            l.setForeground(table.getForeground());
            l.setBackground(table.getBackground());
            table.setGridColor(table.getGridColor());
          
          
          
            if(column == 2){
                if(value != null){
                    if(value instanceof String) {
                        String s = (String)value;
                        if (s.contains("xxx")) {
                            l.setForeground(new Color(0, 0, 255));
                        }else if (s.contains("yyy")) {
                            l.setForeground(new Color(0, 176, 80));
                        }
                    }
                }
            }
          
          
          
            if(hasFocus) {
                l.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, new Color(149, 179, 245)));
            }
          
            return l;
          
          
          
        }
      
      
    }
```


----------



## pappender (1. Apr 2016)

Das muss was mit dem 
	
	
	
	





```
JLabel l = new JLabel((String)value);
```
 und             
	
	
	
	





```
table.setGridColor(table.getGridColor());
```
 zu tun haben. Wenn ich das auskommentiere, gehts wesentlich fixer.


----------



## Thallius (1. Apr 2016)

Ja weil du jedesmal ein Label erzeugst. Bei jedem Zeichnen wird jetzt ein Label mehr auf die Tabelle gezeichnet. Du must schon this zurück geben.


----------



## Flown (1. Apr 2016)

DefaultTableCellRenderer leitet bereits wie @Thallius schon geschrieben hat von JPanel ab und sollte dann so aussehen:

```
class MyTableCellRenderer extends DefaultTableCellRenderer {
  private static final long serialVersionUID = -8993881568812935223L;
 
  private static final Color XXX_COLOR = new Color(0, 0, 255);
  private static final Color YYY_COLOR = new Color(0, 178, 80);
  private static final Color BORDER_COLOR = new Color(149, 179, 245);
 
  @Override
  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
   
    setFont(table.getFont());
    setForeground(table.getForeground());
    setBackground(table.getBackground());
   
    if (column == 2) {
      if (value instanceof String) {
        String s = (String) value;
        if (s.contains("xxx")) {
          setForeground(XXX_COLOR);
        } else if (s.contains("yyy")) {
          setForeground(YYY_COLOR);
        }
      }
    }
    if (hasFocus) {
      setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, BORDER_COLOR));
    }
    return this;
  }
}
```

`value != null` kann man sich sparen weil `null instanceof String == false` ergibt. Man sollte auch nicht immer selben Farben erstellen, nimm einfach Konstanten.


----------

