# Zellen einer JTable unterschiedlich formatieren



## Nachtfalke (29. Dez 2010)

Hallo zusammen,

ich habe noch ein paar Schwierigkeiten mit JTables und habe folgende Frage:

Wie kann ich die Zellen einer JTable unterschiedlich formatieren (Hintergrundfarbe, Font, Ausrichtung, etc.). Kann ich jeder Zelle einen eigenen CellRenderer zuweisen (wenn ja, wie?) oder muss ich allen Zellen den gleichen Renderer zuweisen und im Renderer dann für jede Zelle die Formatierungen codieren?


----------



## Runtime (30. Dez 2010)

Der TableCellRenderer erstellt die Zellen, d. h. du kannst den Zellen den Renderer nicht zuweisen. Wenn du innerhalb der Zelle verschiedene Formatierungen haben willst, dann musst du ein CellRenderer implementieren, der JEditorPanes oder JTextPanes zurückgibt.


----------



## André Uhres (30. Dez 2010)

Hallo Nachtfalke,

gewöhnlich wird ein einziger Cellrenderer verwendet, um alle Zellen zu zeichnen, die die gleiche Art von Daten enthalten (oder alle Zellen einer Spalte). 

Wir können uns den Renderer als konfigurierbaren Stempel denken, den die Tabelle verwendet, um passend formatierte Daten auf jede Zelle zu stempeln. Da dieser "Stempel" konfigurierbar ist, sind auch zellenabhängige Unterschiede möglich:


```
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TestTable1 extends JPanel {

    private JTable table;

    public TestTable1() {
        setLayout(new BorderLayout());
        table = new JTable(10, 10);
        add(new JScrollPane(table));
        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {

            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                int rowM = table.convertRowIndexToModel(row);
                int columnM = table.convertColumnIndexToModel(column);
                if (rowM == 1 && columnM == 2) {
                    c.setBackground(Color.red);
                } else if (rowM == 4 && columnM == 2) {
                    c.setBackground(Color.green);
                } else {
                    c.setBackground(Color.white);
                }
                return c;
            }
        });
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        TestTable1 newContentPane = new TestTable1();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        frame.setVisible(true);
    }
}
```

Wichtig ist, dass die "Konfiguration" immer auch einen "else"-Fall hat, wodurch gleichermaßen die Eigenschaften der "normalen" Zellen gesetzt werden. 

Da wir die Eigenschaften gewöhnlich auf das Model beziehen, ist eine entsprechende Konversion der Zellkoordinaten erforderlich (convertXXXIndexToModel).

Die if-Bedingungen müssen natürlich nicht explizite Zeilen- und Spaltennummern sein, sondern können sich z.B. auch auf die Daten der darzustellenden Zelle oder benachbarter Zellen beziehen. 

Die Werte der Eigenschaften (wie hier die "Background" Eigenschaft) müssen ebenfalls nicht unbedingt explizit angegeben werden, sondern können selbstverständlich auch von Collections oder anderen Objekten geholt werden.

Gruß,
André


----------



## Nachtfalke (30. Dez 2010)

Erstmal danke für die ausführliche Erklärung. Wenn ich das richtig verstanden habe, muss ich also ein Speicherobjekt (z.B. einen Vector) anlegen, in dem ich die Formatierungen speichere, wenn ich die Formatierung einzelner Zellen zur Laufzeit ändern möchte, und dann in der Methode getTableCellRendererComponent diesen Vector auslesen, um die Formatierungen entsprechend zu setzen?

@Runtime: Es geht nicht um verschiedene Formatierungen innerhalb einer Zelle, sondern um unterschiedlich formatierte Zellen innerhalb einer Tabelle.


----------



## André Uhres (30. Dez 2010)

Nachtfalke hat gesagt.:


> Wenn ich das richtig verstanden habe, muss ich also ein Speicherobjekt (z.B. einen Vector) anlegen, in dem ich die Formatierungen speichere, wenn ich die Formatierung einzelner Zellen zur Laufzeit ändern möchte, und dann in der Methode getTableCellRendererComponent diesen Vector auslesen, um die Formatierungen entsprechend zu setzen?



Das geht in die richtige Richtung. Allerdings würde ich "Vector" vermeiden, weil diese Klasse veraltet ist. Aber es stehen ja genug andere Collection und Map Klassen zur Verfügung, wo wir eine geeignete auswählen können.

Gruß,
André


----------



## Landei (30. Dez 2010)

Alles was Sie über CellRenderer wissen wollten, sich aber nie zu fragen trauten: How to Use Tables (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)


----------



## André Uhres (30. Dez 2010)

Landei hat gesagt.:


> Alles was Sie über CellRenderer wissen wollten...



@Landei: in Bezug auf den CellRenderer wird um Tutorial von Oracle leider nichts über die oft notwendige Konversion der Zellkoordinaten gesagt, was für Anfänger zum Problem werden kann.

Gruß,
André


----------



## Nachtfalke (30. Dez 2010)

André Uhres hat gesagt.:


> Das geht in die richtige Richtung. Allerdings würde ich "Vector" vermeiden, weil diese Klasse veraltet ist. Aber es stehen ja genug andere Collection und Map Klassen zur Verfügung, wo wir eine geeignete auswählen können.



Vector war jetzt das erste, was mir eingefallen ist ;-). Dann werde ich mal mein Glück versuchen. Danke nochmal für die Hilfe.


----------

