# Jtable defaultRenderer wohin damit ?



## student86 (5. Okt 2017)

Hallo Leute,

mein Ziel ist es Daten die aus einer Datenbank stammen in einem Viewer (Jtable) anzuzeigen (bis hier läuft alles) aber wenn in Spalte 10 eine "1" eingetragen ist soll die Zeile "grün" darzustellen.

Habe nun einiges darüber gelesen den Renderer zu bearbeiten, aber ich wieß nicht wo dieser hingehört ?


```
public class DB_Viewer extends JFrame {

    private final int small = 50;
    private final int big = 150;


    public static JTable table;

    public DB_Viewer() {
        getContentPane().setLayout(null);
        table = new JTable(new SimpleTableModel());


        JScrollPane sPane = new JScrollPane(table);
        sPane.setBounds(0, 0, 1184, 822);

        getContentPane().add(sPane);
        this.setSize(1200, 940);
      
   
        sPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        sPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        this.setVisible(true);
    }

      public void setColumnWidth() {
        for (int i = 0; i < table.getColumnCount(); i++) {
           TableColumn c = table.getColumnModel().getColumn(i);
            c.setPreferredWidth(150);
        }
    }

    public static void main(String[] args) {
        new DB_Viewer();
    }
}

class SimpleTableModel extends DefaultTableModel {

    private int rows = 30, iZeilen=main.DB_title.length;
    private Object[] rowData = new Object[iZeilen];

    public SimpleTableModel() {
        super();
        initModelData(); 
      
    }
    private void initModelData() {
        System.out.println( "Datenbank Schreiben " );
      
  
        for (int i = 0; i < iZeilen; i++) {
       
            this.addColumn(main.DB_title[i]);
        }
        for (int j = 0; j < rows; j++) {
            for (int i = 0; i < iZeilen; i++) {
                rowData[i] = main.sDatenbankinhalt[j][i];
              
            }
            this.addRow(rowData);

         
        } 
    } 
}
```


----------



## Robat (5. Okt 2017)

Was genau meinst du mit "Du weißt nicht wo der Rendern hingehört?"


----------



## thet1983 (5. Okt 2017)

Wenn du deinem Table einen Renderer hinzufügen willst dann musst du 
die set-Methode verwenden. 

```
table.setDefaultRenderer(Class<?> class, TableCellRenderer);
```
https://docs.oracle.com/javase/8/do...ng.Class-javax.swing.table.TableCellRenderer-


----------



## student86 (5. Okt 2017)

Anschließend füge ich die Funktion hinzu


```
public class myRenderer implements TableCellRenderer {
}
```

weiß da aber irgendwie nicht mit umzugehen,  kennt Ihr vllt einen Link wo ich mal Grundlagen diesbezüglich nachlesen, versteh da denke ich was Grundlegend nicht.


----------



## thet1983 (5. Okt 2017)

das ist keine Funktion das ist eine Klasse und Klassennamen sollten immer mit einem Großbuchstaben beginnen

```
public class MyRenderer implements TableCellRenderer {
}
```

http://www.java2s.com/Tutorial/Java/0240__Swing/implementsTableCellRenderer.htm

http://www.javapractices.com/topic/TopicAction.do?Id=168


----------



## student86 (13. Dez 2017)

Den Renderer habe ich nun zugewiesen aber mein Print im Renderer wird nie aufgerufen... ?


```
getContentPane().setLayout(null);
        table = new JTable(new SimpleTableModel());
        System.out.println("renderer ruweisen");
        table.setDefaultRenderer(Color.class, new ColorTableCellRenderer());
      
        JScrollPane sPane = new JScrollPane(table);
```



```
class ColorTableCellRenderer extends DefaultTableCellRenderer{
   
       
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column);
             System.out.println("Ausführung Renderer");
      ....
...
...
   
            return this;
        }
    }
```


Das "System.out.println("Ausführung Renderer");" wird nie ausgeführt.
Wird der renderer vllt. nicht aufgerufen weil ich ein SimpleTableModel verwende ?


----------



## Thallius (13. Dez 2017)

Nein, sondern weil es keine Spalte gibt die eine Color als Klasse hat. Du must schon das angeben was dageändert werden soll. In Deinem Fall wahrscheinlich String.class oder Integer.class oder sowas.


----------



## student86 (13. Dez 2017)

Also ich beschreibe meine Tabelle mit einem String Array.


```
class SimpleTableModel extends DefaultTableModel {

    private Object[] rowData = new Object[main.DB_title.length];

    public SimpleTableModel() {
        super();
        initModelData(); 
      
    }
   
    public  void initModelData() {
        System.out.println( "Datenbank Schreiben " );
        for (int i = 0; i < main.DB_title.length; i++) {
            this.addColumn(main.DB_title[i]);
        }
        for (int j = 0; j < main.Anzahl_Teile_in_DB; j++) {
            for (int i = 0; i < main.DB_title.length; i++) {
                rowData[i] = main.sDatenbankinhalt[j][i];
            }
            this.addRow(rowData); 
   
        }  
    }  
}
```


----------



## thet1983 (13. Dez 2017)

student86 hat gesagt.:


> table.setDefaultRenderer(Color.*class*, *new* ColorTableCellRenderer()


kann schon mal nicht funktionieren...hast du im Model eine Cell die von Color stammt? Nein!

Deine Daten sind alle String s oder?
Nun was glaubst du was statt Color.class jetzt hin gehört?
Richtig :* String.class*

was gibt diese Methode zurück?


student86 hat gesagt.:


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



Richtig : *Component*
Component ist die Mutterklasse von?
Richtig: Button, Textcomponents...etc

Also was muss ich wohl machen wenn diese Methode einen Rückgabewert benötigt?
Richtig : ich geb im einen ( ein TextField, Label, Button.....)

nur demo code

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

       JTextField cell = new JTextField();
       cell.setText((value == null)? "NO VALUE" : value.toString());
       cell.setBackground((value.toString().equals("1"))? Color.green : table.getBackground());
       // selbst implementierten !!
       // isSelected && hasFocus TODO
       return cell;
```


----------



## student86 (13. Dez 2017)

Vielen Dank, die super ausführliche Erklärung hat mir das ganze mal ein bisschen näher gebracht.

Musste im Aufruf ein Objekt einsetzen

```
table = new JTable(new SimpleTableModel());
        System.out.println("renderer zuweisen");
        table.setDefaultRenderer(Object.class, new ColorTableCellRenderer());
```

Nun werden aber auch die Maße Höhe und Breite der Celle überschrieben und die Einstellungen aus dem SimpleTableModel gehen verloren(Anhang). Muss ich die nun alle per Hand wieder gerade biegen ?


----------



## thet1983 (13. Dez 2017)

du kannst auch JLabel oder Buttons verwenden...
die Methode getTableCellRenderComponent besitzt übergabe parameter die du verwenden kannst
zb int column -> 0: erste col, 1: zweite etc...

da muss man sich ein bisschen spielen, bis es so passt wie man sich das vorstellt..


----------



## student86 (14. Dez 2017)

Es geht voran 

Mit einen JTextfield wird die Tabelle sehr langsam und stottert sehr beim scrollen. habe nun zum JLabel gewechselt.

```
class ColorTableCellRenderer extends DefaultTableCellRenderer{
   
     @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column);
            System.out.println("Ausführung Renderer");
     // Mit einem JTextfield stottert die Tabelle      
            //JTextField cell = new JTextField();
            JLabel cell = new JLabel();
            //cell.setBounds(100, 100, 100, 100);
            cell.setText((value == null)? "NO VALUE" : value.toString());
    //        cell.setBackground((value.toString().equals("1"))? Color.green : table.getBackground());
            cell.setForeground(Color.RED);
     // Bleibt weiß
            cell.setBackground(Color.GREEN);
          
            table.setRowHeight( 22 );
          
            // selbst implementierten !!
            // isSelected && hasFocus TODO
             return cell;
          
        }
```

Ich habe jetzt ja mit dem ColorTableCellRenderer das damalige SimpleTableModel überschrieben!?  Was hat das SimpleTableModel denn verwendet ?  Auch ein  JTextArea oder JLabels oder . ...  ?  Weil damals hat die Tabelle ohne Renderer nicht glaggt.


----------



## Thallius (14. Dez 2017)

Der Renderer hat mit dem Modell überhaupt nichts zu tun. Das Model liefert die Daten, der Renderer stellt sie dar.


----------



## Thallius (14. Dez 2017)

Ich verstehe auch nicht was du da eigentlich machst. Ich dachte du willst nur die Hintergrundfarbe ändern je nachdem was in der Zelle steht. Warum machst du das dann nicht einfach.


```
if(column == DeinSpaltenIndex)
{
    if(value.equals("1")
        setBackground(Color.DeineFarbeFür1);
}
return this;
```

Das wars schon


----------



## X5-599 (14. Dez 2017)

Nicht ganz, oder? Ist es bei diesen Renderen nicht so, dass man immer dafür zu sorgen hat, dass ein "definierter" Zustand des Labels besteht? Also wenn man, wie hier, den background ändert gilt dieser dann für alle Zellen, die gerendert werden. Hier: ab dem Zeitpunkt wo ein value von "1" auftritt werden nur noch "DeineFarbeFür1" farbene Zellen gerendert.


----------



## truesoul (14. Dez 2017)

Hallo.

Ich will nur mal diesen Link reinwerfen:
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html

Grüße


----------



## Thallius (14. Dez 2017)

X5-599 hat gesagt.:


> Nicht ganz, oder? Ist es bei diesen Renderen nicht so, dass man immer dafür zu sorgen hat, dass ein "definierter" Zustand des Labels besteht? Also wenn man, wie hier, den background ändert gilt dieser dann für alle Zellen, die gerendert werden. Hier: ab dem Zeitpunkt wo ein value von "1" auftritt werden nur noch "DeineFarbeFür1" farbene Zellen gerendert.



Und warum frage ich wohl davor die Spalte ab?


----------



## X5-599 (14. Dez 2017)

Meiner Erfahrung nach wird das doch aber nichts nützen. Sobald das setBackgorund einmal gesetzt wurde hat das Label diesen Hintergrund. Alle Zellen, für die dieser Renderer zuständig ist werden dann mit dieser Farbe gerendert.


----------



## truesoul (14. Dez 2017)

Ignorieren


----------



## student86 (14. Dez 2017)

> Ich verstehe auch nicht was du da eigentlich machst. Ich dachte du willst nur die Hintergrundfarbe ändern je nachdem was in der Zelle steht. Warum machst du das dann nicht einfach.
> 
> Code (Text):
> 
> ...



Das Funktioniert ja auch , alle Zeilen die eine 1 Beinhalten werden grün. Siehe Angehängtes Bild.

Nur ist die Tabelle nun unbrauchbar, weil sie sehr stark laggt,


```
class ColorTableCellRenderer extends DefaultTableCellRenderer{
    
     @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column);
            System.out.println("Ausführung Renderer");
     // Mit einem JTextfield stottert die Tabelle       
            JTextField cell = new JTextField();
           // JLabel cell = new JLabel();

            cell.setText(value.toString());
            if (value.toString().equals("1")){
                cell.setBackground(Color.green);
            }
            table.setRowHeight( 22 );
           
            // selbst implementierten !!
            // isSelected && hasFocus TODO
             return cell;   
        }
    }
```


----------



## truesoul (14. Dez 2017)

X5-599 hat gesagt.:


> Meiner Erfahrung nach wird das doch aber nichts nützen. Sobald das setBackgorund einmal gesetzt wurde hat das Label diesen Hintergrund. Alle Zellen, für die dieser Renderer zuständig ist werden dann mit dieser Farbe gerendert.



Jein, also der Hintergrund lässt sich weiterhin verändern und die Variante von @Thallius ist schon korrekt bzw funktioniert auch. Wird auch offiziell so gemacht siehe link von vorhin.


```
table.setDefaultRenderer(String.class, new ColorRenderer());

public class ColorRenderer extends JLabel implements TableCellRenderer {
    public ColorRenderer() {
        setOpaque(true);
    }

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

        int selectedColumn = table.getSelectedColumn();
        int selectedRow = table.getSelectedRow();

        setBackground(Color.WHITE);

        if (isSelected) {
            if (selectedRow == row && column == selectedColumn)
                setBackground(Color.RED);
        }

        setText(String.valueOf(object));
        return this;
    }
}
```

Grüße


----------



## student86 (14. Dez 2017)

Das Laggen lag am JTextfield. Ohne die erstellte "cell" und nur mit

```
if (value.toString().equals("1")){
                 setBackground(Color.green);
             }
```
läuft es flüssig


----------



## student86 (14. Dez 2017)

Etapenziel erreicht. Vielen Dank! eine Einzelne Zelle in einer bestimmten Spalte ist nun grün wenn der Inhalt true ist.


```
class ColorTableCellRenderer extends DefaultTableCellRenderer{
    
     @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column);
           
            if (value.toString().equals("true")){
                if(column==73){
                    setBackground(Color.green);
                }
            }
            else if((row%2)==0){
                setBackground(Color.white);
            }
            else{
                setBackground(Color.lightGray);
            }           
            table.setRowHeight( 22 );
             return this;   
        }
```

nächstes Ziel -> Die ganze Zeile einfärben


----------



## student86 (14. Dez 2017)

Ganze Zeile Farbig klappt so:


```
class ColorTableCellRenderer extends DefaultTableCellRenderer{
    
     @Override
        public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column);

            if (table.getValueAt(row, 73).toString().equals("true")){
                setBackground(Color.red);
            }
            else if((row%2)==0){
                setBackground(Color.white);
            }
            else{
               
                setBackground(Color.lightGray);
            }           
            table.setRowHeight( 22 );
             return this;   
        }
    }
```


----------

