# Bei JTable eine bestimmte Zelle färben



## Guest (25. Apr 2007)

Hallo!

Ich habe mir mit Hilfe einer JTable so eine Art Terminplan erstellt. Dabei sollte es im Menü eine Möglichkeit geben, die Farbe der Selektierten Zelle zu ändern. Wenn man darauf klickt, wird der ActionListener informiert und fragt von der JTable die Koordinaten der Markierten Zelle ab. Jetzt möchte ich meinem CellRenderer (selbst geschrieben) informieren, dass er diese bestimmte Zelle einfärben soll. Wie mache ich das?
Ich habe schon folgendes versucht:
Im CellRenderer eine Methode setColor(Color c) geschrieben, die die Zellfarbe ändern soll. Wenn ich jetzt aber folgendes mache:

```
JMenuItem Rot=new JMenuItem("Rot");
		Rot.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				TableCellRenderer tcr=Plan.getCellRenderer(Plan.getSelectedRow(),Plan.getSelectedColumn());
                                tcr.setColor(Color.red);
			}
		});
```
erhalte ich in der Zeile 7 (tcr.setColor(Color.red)) eine Fehlermeldung. Woran liegt das?
Gibt es eventuell noch eine bessere Lösung?

(Auch in der Bordsuche habe ich nichts entsprechendes gefunden)

Hier ist mein TableCellRenderer:

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

public class CellRenderer extends JLabel implements TableCellRenderer
{
	public Component getTableCellRendererComponent
	(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column)
	{
		this.setOpaque(true);
		Border b = BorderFactory.createEmptyBorder(1, 1, 1, 1);
	    this.setBorder(b);
	    this.setForeground(table.getForeground());
        this.setBackground(table.getBackground());
	    if (hasFocus)
	    {
	    	this.setBackground(Color.blue);
	    	this.setForeground(Color.red);
	    }
	    else if (isSelected)
	    {
	    	this.setBackground(Color.blue);
     	}
		return this;
	}
	public void setColor(Color c)
	{
		this.setForeground(c);
	}
}
```

Bitte helft mir!


----------



## m@nu (25. Apr 2007)

erst mal: was für eine fehlermeldung erhälst du?

zweitens: die farbänderung (resp. die info, dass sich was geändert hat) sollte vom model her kommen. :meld:
setz also im ActionListener nicht die hintergrundfarbe des renderers auf eine farbe, sondern aktualisier' die daten des entsprechenden elements deines models.
anschliessend rufst du repaint() auf damit deine tabelle neu gezeichnet wird. so wird wiederum dein renderer aufgerufen, welcher entsprechend der neuen daten weis, wie er die zelle zeichnen muss.


----------



## Guest (25. Apr 2007)

1.Ich erhalte folgende Fehlermeldung:
cannot find symbol method setColor(java.awt.Color)


2.


> sondern aktualisier' die daten des entsprechenden elements deines models.


Wie meinst du das? (ich versteh noch nicht wirklich viel davon)  

Kannst du mir vielleicht ein paar Zeilen Tippen?  

Das hier ist mein TableModel:

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

public class TableModel extends AbstractTableModel
{
	static int Rows=10;
	static int Columns=5;
	static Object data[][]=new Object[100][25];
	public Object getValueAt(int row, int column)
	{
		return data[row][column];
	}
	public void setValueAt(Object obj,int row, int column)
	{
		data[row][column]=obj;
	}
	public boolean isCellEditable(int row, int column)
	{
		return true;
	}
	public int getColumnCount()
	{
		return Columns;
	}
	public int getRowCount()
	{
		return Rows;
	}
	public void addRow()
	{
		if(Rows<100)
		Rows++;
		fireTableRowsInserted(1,1);
	}
	public void removeRow()
	{
		if(Rows>0)
		Rows--;
		fireTableRowsDeleted(1,1);
	}
	public void addColumn()
	{
		if(Columns<25)
		Columns++;
		fireTableStructureChanged();
	}
	public void removeColumn()
	{
		if(Columns>0)
		Columns--;
		fireTableStructureChanged();
	}
}
```


----------



## norman (25. Apr 2007)

ich schätze du musst auf CellRenderer Casten

```
((CellRenderer)tcr).setColor(Color.RED);
```


----------



## norman (25. Apr 2007)

m@nu hat gesagt.:
			
		

> zweitens: die farbänderung (resp. die info, dass sich was geändert hat) sollte vom model her kommen. :meld:



nicht unbedingt. es ist ja garnicht klar, warum da die farbe geändert werden soll. vllt soll nur was hervorgehoben/markiert werden. das geht das model nix an..


----------



## Guest (25. Apr 2007)

> ich schätze du musst auf CellRenderer Casten



Warum? Es ist doch schon ein CellRenderer-Objekt.
Aber es funktioniert auch so nicht.


----------



## m@nu (25. Apr 2007)

@norman: na, meiner meinung schon... is ne änderung im datenbestand 

ich nehm' jetzt mal an, das "auf rot setzen" soll sowas wie ne markierung für deinen termin sein... ne kategorisierung oder sowas, nicht?


ich werd dir morgen bei gelegenheit ein kleines snippet schreiben, wie ich mir das ganze vorstelle... heute bin ich zu kaputt vom arbeiten 

ps. wie wärs mit nem useraccount statt nem "Gast"?


----------



## André Uhres (26. Apr 2007)

http://www.java-forum.org/de/viewtopic.php?p=145528#145528


----------



## m@nu (26. Apr 2007)

morgen zusammen

@Gast: reicht dir das beispiel von André Uhres oder brauchst du doch noch ein anderes beispiel?


----------



## Guest (26. Apr 2007)

@ m@nu: Wenn es dir nicht zu viel arbeit macht, wäre ich dir sehr dankbar, wenn du mir noch ein zweites (kleines) Beispiel schreibst. Ich habe jetzt das von André angeschaut, habe aber keine Ahnung, wie ich das in mein Programm einbauen soll. Aber grundsätzlich ist die Funktion dieses Programms (Beispiel von André) schon das richtige.
(Bin halt noch ein Anfänger)



> ich nehm' jetzt mal an, das "auf rot setzen" soll sowas wie ne markierung für deinen termin sein... ne kategorisierung oder sowas, nicht?



Ganz genau.


----------



## m@nu (26. Apr 2007)

so... hier mein beispiel (nicht so kurz geraten wie ich zuerst gedacht hab ggg)

File 1: TerminBean.java (dient zum speichern der daten)

```
import java.util.Date;

/*
 * Created on 26.04.2007
 */

/**
 * @author Manuel Alabor
 * @version 1.0
 */
public class TerminBean {

    public enum Flag {
        flagNONE, flagROT, flagGELB
    }
    
    // Members -----------------------------------------------------------------
    private Flag flag;
    private String text;
    private Date date;
    
    
    // Konstruktoren -----------------------------------------------------------
    public TerminBean(String text, Date date) {
        this(text, date, Flag.flagNONE);
    }
    
    public TerminBean(String text, Date date, Flag flag) {
        this.text = text;
        this.flag = flag;
        this.date = date;
    }
    
    
    // Getter- & Setter-Methoden -----------------------------------------------
    public Flag getFlag() {
        return flag;
    }
    public void setFlag(Flag flag) {
        this.flag = flag;
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    
}
```

File 2: TerminTableModel.java (Stellt die TerminBean-instanzen in einem tablemodel zur verfügung)

```
import java.util.ArrayList;

import javax.swing.table.AbstractTableModel;

/*
 * Created on 26.04.2007
 */

/**
 * @author Manuel Alabor
 * @version 1.0
 */
public class TerminTableModel extends AbstractTableModel {
    
    private ArrayList<TerminBean> data;
    
    public TerminTableModel(ArrayList<TerminBean> data) {
        this.data = data;
    }
    
    public int getColumnCount() {
        return 2;
    }
    
    public int getRowCount() {
        return data.size();
    }
    
    public Object getValueAt(int rowIndex, int columnIndex) {
        TerminBean bean = data.get(rowIndex);
        
        if(columnIndex == 0) return bean.getText();
        else if(columnIndex == 1) return bean.getDate();
        else return null;
    }
    
    public TerminBean getBean(int rowIndex) {
        return data.get(rowIndex);
    }

}
```

File 3: TerminFrame.java (macht ein gui und hat den entsprechenden renderer implementiert)

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

/*
 * Created on 26.04.2007
 */

/**
 * @author Manuel Alabor
 * @version 1.0
 */
public class TerminFrame extends JFrame {

    @SuppressWarnings("deprecation")
    public TerminFrame() {
        super("TerminTable");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocation(300,300);
        setSize(400,300);
        
        // Daten:
        ArrayList<TerminBean> data = new ArrayList<TerminBean>();
        data.add(new TerminBean("Test 1", new Date(2007,05,01)));
        data.add(new TerminBean("Test 2", new Date(2007,05,02), TerminBean.Flag.flagROT));
        data.add(new TerminBean("Test 3", new Date(2007,05,03)));
        data.add(new TerminBean("Test 4", new Date(2007,05,04)));
        final TerminTableModel model = new TerminTableModel(data);
        
        /* GUI: */
        JPanel gui = new JPanel(new BorderLayout());
        
        // Table
        final JTable table = new JTable(model);
        TerminCellRenderer renderer = new TerminCellRenderer();
        table.getColumnModel().getColumn(0).setCellRenderer(renderer);
        table.getColumnModel().getColumn(1).setCellRenderer(renderer);
        
        // Buttons:
        final JButton btnNone = new JButton("None");
        final JButton btnGelb = new JButton("Gelb");
        final JButton btnRot = new JButton("Rot");
        ActionListener buttonActionListener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(table.getSelectedRow() > -1) {
                    TerminBean.Flag newFlag = TerminBean.Flag.flagNONE;
                    
                    if(e.getSource() == btnGelb) {
                        newFlag = TerminBean.Flag.flagGELB;
                    } else if(e.getSource() == btnRot) {
                        newFlag = TerminBean.Flag.flagROT;
                    }
                    
                    TerminBean selectedBean = model.getBean(table.getSelectedRow());
                    selectedBean.setFlag(newFlag);
                    table.repaint();
                } else {
                    System.out.println("Zuerst eine Zeile auswählen!");
                }
            }
        };
        btnNone.addActionListener(buttonActionListener);
        btnGelb.addActionListener(buttonActionListener);
        btnRot.addActionListener(buttonActionListener);
        
        JPanel buttons = new JPanel();
        buttons.add(btnNone);
        buttons.add(btnGelb);
        buttons.add(btnRot);
        
        
        // Zusammensetzen:
        gui.add(buttons, BorderLayout.NORTH);
        gui.add(new JScrollPane(table), BorderLayout.CENTER);
        setContentPane(gui);
    }
    
    private class TerminCellRenderer extends DefaultTableCellRenderer {
        private SimpleDateFormat format = new SimpleDateFormat("dd.MM.y");
        
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            
            // Falls hier ein Datum angezeigt werden soll, dieses formatieren:
            if(value instanceof Date) {
                setText(format.format(value));
            }
            
            // TerminBean holen & background setzen:
            TerminBean bean = ((TerminTableModel)table.getModel()).getBean(row);
            if(bean.getFlag() == TerminBean.Flag.flagROT) {
                setBackground(Color.red);
            } else if(bean.getFlag() == TerminBean.Flag.flagGELB) {
                setBackground(Color.yellow);
            } else {
                setBackground(table.getBackground());                
            }
            
            // Renderer zurückgeben:
            return TerminCellRenderer.this;
        }
    }
    
    // Testing-Code ------------------------------------------------------------
    public static void main(String[] args) {
        new TerminFrame().setVisible(true);
    }
    
    
}
```


vorallem im TerminFrame ist der GUI-erstellungscode nicht wirklich mustergültig. aber es funktioniert. 
hoffe aber, dieser code verdeutlicht dir das zusammenspiel von model & renderer.


----------



## André Uhres (26. Apr 2007)

Anonymous hat gesagt.:
			
		

> ..Ich habe jetzt das von André angeschaut, habe aber keine Ahnung, wie ich das in mein Programm einbauen soll...


Hier ist nochmal alles zusammengefasst, worauf es in meinem Beispiel ankommt.

Du braucht dazu keinen eigenen Renderer!
Du überschreibst einfach die Methode "prepareRenderer" von JTable genau wie unten angegeben.
Die Methode "colorButtonActionPerformed" kannst du auch genau so übernehmen.
"colorButtonActionPerformed" rufst du dann auf, um die selektierten Zellen mit "red" oder "white" zu markieren. Fertig!

```
...
public class Kreuz_Tabelle_1 extends JFrame{
...
    private HashMap<String, String> colorMap = new HashMap<String, String>();
    private final Color redSelected = new Color(255,150,150);
    public Kreuz_Tabelle_1() {
...
        table = new JTable() {
            public Component prepareRenderer(
                    final TableCellRenderer renderer, final int row, final int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                String key = row+":"+column;
                c.setBackground(Color.white );
                boolean selected = isRowSelected(row) && isColumnSelected(column);
                if( selected ){
                    c.setBackground(Color.cyan);
                }
                String colorValue = colorMap.get(key);
                if( colorValue!=null ){
                    if( (colorValue).equals("red") ){
                        c.setBackground(Color.red);
                        if( selected ){
                            c.setBackground(redSelected);
                        }
                    }
                    if( (colorValue).equals("white") ) {
                        c.setBackground(Color.white);
                        if( selected ){
                            c.setBackground(Color.cyan);
                        }
                    }
                }
                return c;
            }
        };
...
    }
    private void colorButtonActionPerformed(final String color) {//Parameter: "red" oder "white"
        int[] row = table.getSelectedRows();
        int[] column = table.getSelectedColumns();
        for (int i = 0; i < row.length; i++) {
            for (int j = 0; j < column.length; j++) {
                String key = row[i]+":"+column[j];
                String value = table.getValueAt(row[i],column[j]).toString();
                colorMap.put(key, color);
            }
        }
        table.updateUI();
    }
...
```


----------

