# Farbe einer Zelle in JTable ändern



## Supersimsonfahrer (29. Jan 2006)

Hey Leute,

Wie kann ich die Farbe einer ganz bestimmten Zelle in einer JTable zur laufzeit ändern?
Beispielsweise wenn ein Button geklickt wird.

Das Prog stellt die Sudoku-Problematik dar,
und ich will die zellfarbe auf rot setzen, wenn ein konflikt mit den Benutzereingaben auftritt.
In Codezeile 103 wäre eine dieser stellen...

könnt ihr mir helfen???


```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;



public class Sudoku extends JFrame {

	public boolean fertig = false;
	private JTable tabelle;
	private	int array[][]= new int[9][9];
	
	private Sudoku(){
	String wert[][] = new String[9][9];
	String spalte[]= {"1","2","3","4","5","6","7","8","9"};
		
		
		for (int i=0; i<9; i++) {
			for (int j=0; j<9; j++) {
				wert[i][j]="0";
			}
		}
		JButton btnPruefen = new JButton("Prüfen");
		JButton btnLoesen = new JButton("Lösen");
		JButton btnLoeschen = new JButton("Löschen");
		JPanel controll = new JPanel();
		controll.setLayout(new FlowLayout());
		controll.add(btnPruefen);
		controll.add(btnLoesen);
		controll.add(btnLoeschen);
		
		
		
		tabelle = new JTable(wert, spalte);
		tabelle.setPreferredSize(new Dimension(200,150));

		//Zellenausrichtung
		DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
	    renderer.setHorizontalAlignment(DefaultTableCellRenderer.CENTER);
	    for (int i=0; i<9; i++) {
	    	tabelle.getColumnModel().getColumn(i).setCellRenderer(renderer);
		}
	    
	      
		getContentPane().add(tabelle, BorderLayout.CENTER);
		getContentPane().add(controll, BorderLayout.SOUTH);
		setTitle("Sudoku");
		pack();
		setVisible(true);
		
		
		
		
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				setVisible(false);
				System.exit(0);
			}
		});
		btnPruefen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				zellenPruefen();
			}
		});
		btnLoesen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				loesen();
			}
		});
		btnLoeschen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				loeschen();
			}
		});
		
		
	}
	
	private boolean zellenPruefen(){
		boolean check = true;
		int inhalt, a, b = 5;
		
		for(int x = 0; x<9; x++){
			for(int y = 0; y<9; y++){
				inhalt = Integer.parseInt((String)tabelle.getValueAt(x,y).toString());
				if(inhalt >=0 && inhalt <= 9 ){
					//quadrat überprüfen
					a = x / 3 + 1;
					b = y / 3 + 1;
					if(Integer.parseInt((String)tabelle.getValueAt(x,y).toString()) == inhalt  & (a * 3 - 1 != x) & (b * 3 - 1 != y)){
						check = false;
						/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
						hier soll zellfarbe geändert werden
						!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
					}
					
					//waagerecht prüfen
					for(int j=0; j<9; j++){
						if(Integer.parseInt((String)tabelle.getValueAt(j,y).toString()) == inhalt & j != x){
							 check = false;
							 //farbe ändern
						}
					}
					for(int k=0; k<9; k++){
						if(Integer.parseInt((String)tabelle.getValueAt(x,k).toString()) == inhalt & k != y){
							 check = false;
							 //farbe ändern
						}
					}
				}
			}
		}
		return check;
	}
	private void loesen(){
		for (int x =0; x<9; x++){
			for (int y =0; y<9; y++){
				array[x][y]=Integer.parseInt((String)tabelle.getValueAt(x,y).toString());
			}
		}
		fertig = false;
		sudokuRek(0, 0);
	}
	private void sudokuRek(int x, int y){
		boolean check;
		int a = 0, b = 0;
		
		Thread.yield(); // erlaube AktivitÄaten anderer Threads
		
		if(array[x][y] == 0){
			
			for(int i = 1; i <= 9; i++){
				if(fertig == true){
					break;
				}
				check = true;
				//quadrat überprüfen
				a = x / 3 + 1;
				b = y / 3 + 1;
				if(array[a * 3 - 1][ b * 3 - 1] == i){check = false;}
				if(array[a * 3 - 2][ b * 3 - 1] == i){check = false;}
				if(array[a * 3 - 3][ b * 3 - 1] == i){check = false;}
				if(array[a * 3 - 1][ b * 3 - 2] == i){check = false;}
				if(array[a * 3 - 2][ b * 3 - 2] == i){check = false;}
				if(array[a * 3 - 3][ b * 3 - 2] == i){check = false;}
				if(array[a * 3 - 1][ b * 3 - 3] == i){check = false;}
				if(array[a * 3 - 2][ b * 3 - 3] == i){check = false;}
				if(array[a * 3 - 3][ b * 3 - 3] == i){check = false;}
				
				
				for(int j=0; j<9; j++){
					if(array[j][y] == i){check = false;}
				}
				for(int k=0; k<9; k++){
					if(array[x][k] == i){check = false;}
				}
				if(check == true){
					array[x][y]=i;
					if(x < 8){sudokuRek(x+1, y);}
					if(x == 8 & y < 8){sudokuRek(0,y+1);}
					if(x == 8 & y == 8){ausgabe();fertig = true;}
					array[x][y]=0;
				}//ende check
			}//ende for bis 9
		}//ende array = 0
		
		else if (array[x][y]>0) {
			if(x < 8){sudokuRek(x+1, y);}
			else if(x == 8 & y < 8){sudokuRek(0,y+1);}
			else if(x == 8 & y == 8){
				ausgabe();
				fertig = true;
			}
		} 
	}
	private void ausgabe(){
		for (int x =0; x<9; x++){
			for (int y =0; y<9; y++){
				tabelle.setValueAt(String.valueOf(array[x][y]),x,y);
			}
		}
	}
	private void loeschen(){
		for (int x =0; x<9; x++){
			for (int y =0; y<9; y++){
				tabelle.setValueAt("0",x,y);
			}
		}
	}
	public static void main(String[] args){
		new Sudoku();
	}
}
```


----------



## Timmah (29. Jan 2006)

Setz doch, wenn du die Farbe der Zelle ändern willst, einen neuen CellRenderer für die Zelle, in dem die Farbe entsprechende gesetzt wird.


----------



## Super simsonfahrer (29. Jan 2006)

bin kein wirklicher anfänger
aber sowas hab ich noch net gemacht

kannst du mir net n beispiel geben???


----------



## Roar (29. Jan 2006)

:arrow: http://www.java-forum.org/de/viewtopic.php?t=5321


----------



## Timmah (29. Jan 2006)

```
private class MyTableCellRenderer extends javax.swing.table.DefaultTableCellRenderer
    {
        private int zeile = 0;
        private int spalte = 0;
    	public MyTableCellRenderer(int zeile, int spalte)
    	{
    		this.zeile = zeile;
                this.spalte = spalte;

    	}
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (row == zeile && column == spalte)
            {
                setForeground(Color.RED);
                
            }
            else
            {
                setForeground(Color.BLACK);
                
            }

            return this;
        }
    }
```

Dann zur Laufzeit 


```
jtable.setDefaultRenderer(Object.class, new MyTableCellRenderer(12,34));
```

Ist nicht getestet, könnte aber funktionieren 

EDIT: Eben getestet -> funktioniert 
Sollte aber das nächste mal nicht so gutmütig sein, und gleich die Lösung für etwas sagen, was man auch in der Hilfe findet^^


----------



## Supersimsonfahrer (29. Jan 2006)

Äh???
bin ich sogar zu dumm um den gegebenen Quelltext anzupassen?
bei mir funzt das net zur Laufzeit


```
tabelle.setDefaultRenderer(Integer.class, new MyTableCellRenderer(1,1));
```


----------



## Timmah (29. Jan 2006)

Nicht


```
Integer.class
```

Mach es so, wie es oben steht


```
Object.class
```

Dann funzt das auch. Ich habe die den Quelltext quasi schon fertig gegeben, du musst nur noch die Zellendaten im Konstruktor mitgeben, die es bei dir sind.


----------



## Supersimsonfahrer (29. Jan 2006)

wenn ich dich nerve dann sag bitte bescheit  :lol: 

hab es jetzt wieder nach deiner vorgabe geändert,
aber das funzt bei mir nicht

wenn ich in eclipse nen haltepunkt setze in der Zeile 16 bzw. 21 in der MyTableCellRenderer -Class
und den debug-modus laufen lasse, springt er da nie rein.
Und das müsste er doch früher oder später tun wenn ich mich nicht täusche, oder net???


----------



## Timmah (29. Jan 2006)

Also an dem Punkt, wo du die Zellenfarbe ändern willst, rufst du die setDefaultRenderer() Methode auf. In diesem Moment wird diese aufgerufen, in die Klasse MyTableCellRenderer gesprungen, und der Code dort ausgeführt.

Falls er da nicht reinspringt, hast du, wie soll es anders sein, irgendwas falsch gemacht 

Poste einfach mal den Code.

EDIT: Was ich da oben geschrieben habe ist Käse. Erst wenn dem Model neue Daten hinzugefügt werden wird der Renderer aufgerufen...


----------



## Supersimsonfahrer (29. Jan 2006)

hauptklasse:

```
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;



public class Sudoku extends JFrame {

   public boolean fertig = false;
   private JTable tabelle;
   private   int array[][]= new int[9][9];
   
   private Sudoku(){
   String wert[][] = new String[9][9];
   String spalte[]= {"1","2","3","4","5","6","7","8","9"};
      
      
      for (int i=0; i<9; i++) {
         for (int j=0; j<9; j++) {
            wert[i][j]="0";
         }
      }
      JButton btnPruefen = new JButton("Prüfen");
      JButton btnLoesen = new JButton("Lösen");
      JButton btnLoeschen = new JButton("Löschen");
      JPanel controll = new JPanel();
      controll.setLayout(new FlowLayout());
      controll.add(btnPruefen);
      controll.add(btnLoesen);
      controll.add(btnLoeschen);
      
      
      
      tabelle = new JTable(wert, spalte);
      tabelle.setPreferredSize(new Dimension(200,150));

      //Zellenausrichtung
      DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
      renderer.setHorizontalAlignment(DefaultTableCellRenderer.CENTER);
      for (int i=0; i<9; i++) {
          tabelle.getColumnModel().getColumn(i).setCellRenderer(renderer);
      }

      getContentPane().add(tabelle, BorderLayout.CENTER);
      getContentPane().add(controll, BorderLayout.SOUTH);
      setTitle("Sudoku");
      pack();
      setVisible(true);
      
      
      
      
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            setVisible(false);
            System.exit(0);
         }
      });
      btnPruefen.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            zellenPruefen();
         }
      });
      btnLoesen.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            loesen();
         }
      });
      btnLoeschen.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            loeschen();
         }
      });
      
      
   }
   
   private boolean zellenPruefen(){
      boolean check = true;
      int inhalt, a, b = 5;
      
      for(int x = 0; x<9; x++){
         for(int y = 0; y<9; y++){
            inhalt = Integer.parseInt((String)tabelle.getValueAt(x,y).toString());
            if(inhalt >=0 && inhalt <= 9 ){
               //quadrat überprüfen
               a = x / 3 + 1;
               b = y / 3 + 1;
               if(Integer.parseInt((String)tabelle.getValueAt(x,y).toString()) == inhalt  & (a * 3 - 1 != x) & (b * 3 - 1 != y)){
                  check = false;
                  tabelle.setDefaultRenderer(Object.class, new MyTableCellRenderer(1,1));
               }
               
               //waagerecht prüfen
               for(int j=0; j<9; j++){
                  if(Integer.parseInt((String)tabelle.getValueAt(j,y).toString()) == inhalt & j != x){
                      check = false;
                      tabelle.setDefaultRenderer(Object.class, new MyTableCellRenderer(1,1));
                  }
               }
               //senkrecht prüfen
               for(int k=0; k<9; k++){
                  if(Integer.parseInt((String)tabelle.getValueAt(x,k).toString()) == inhalt & k != y){
                      check = false;
                      tabelle.setDefaultRenderer(Object.class, new MyTableCellRenderer(1,1));
                  }
               }
            }
         }
      }
      return check;
   }
   private void loesen(){
      for (int x =0; x<9; x++){
         for (int y =0; y<9; y++){
            array[x][y]=Integer.parseInt((String)tabelle.getValueAt(x,y).toString());
         }
      }
      fertig = false;
      sudokuRek(0, 0);
   }
   private void sudokuRek(int x, int y){
      boolean check;
      int a = 0, b = 0;
      
      Thread.yield(); // erlaube AktivitÄaten anderer Threads
      
      if(array[x][y] == 0){
         
         for(int i = 1; i <= 9; i++){
            if(fertig == true){
               break;
            }
            check = true;
            //quadrat überprüfen
            a = x / 3 + 1;
            b = y / 3 + 1;
            if(array[a * 3 - 1][ b * 3 - 1] == i){check = false;}
            if(array[a * 3 - 2][ b * 3 - 1] == i){check = false;}
            if(array[a * 3 - 3][ b * 3 - 1] == i){check = false;}
            if(array[a * 3 - 1][ b * 3 - 2] == i){check = false;}
            if(array[a * 3 - 2][ b * 3 - 2] == i){check = false;}
            if(array[a * 3 - 3][ b * 3 - 2] == i){check = false;}
            if(array[a * 3 - 1][ b * 3 - 3] == i){check = false;}
            if(array[a * 3 - 2][ b * 3 - 3] == i){check = false;}
            if(array[a * 3 - 3][ b * 3 - 3] == i){check = false;}
            
            
            for(int j=0; j<9; j++){
               if(array[j][y] == i){check = false;}
            }
            for(int k=0; k<9; k++){
               if(array[x][k] == i){check = false;}
            }
            if(check == true){
               array[x][y]=i;
               if(x < 8){sudokuRek(x+1, y);}
               if(x == 8 & y < 8){sudokuRek(0,y+1);}
               if(x == 8 & y == 8){ausgabe();fertig = true;}
               array[x][y]=0;
            }//ende check
         }//ende for bis 9
      }//ende array = 0
      
      else if (array[x][y]>0) {
         if(x < 8){sudokuRek(x+1, y);}
         else if(x == 8 & y < 8){sudokuRek(0,y+1);}
         else if(x == 8 & y == 8){
            ausgabe();
            fertig = true;
         }
      }
   }
   private void ausgabe(){
      for (int x =0; x<9; x++){
         for (int y =0; y<9; y++){
            tabelle.setValueAt(String.valueOf(array[x][y]),x,y);
         }
      }
   }
   private void loeschen(){
      for (int x =0; x<9; x++){
         for (int y =0; y<9; y++){
            tabelle.setValueAt("0",x,y);
         }
      }
   }
   public static void main(String[] args){
      new Sudoku();
   }
}
```

MyTableCellRenderer:

```
import java.awt.Color;
import java.awt.Component;

import javax.swing.JTable;

public class MyTableCellRenderer extends javax.swing.table.DefaultTableCellRenderer{

	private int zeile = 0;
    private int spalte = 0;
   public MyTableCellRenderer(int zeile, int spalte)
   {
      this.zeile = zeile;
      this.spalte = spalte;

   }
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (row == zeile && column == spalte)
        {
            setForeground(Color.RED); 
        }
        else
        {
            setForeground(Color.BLACK);
        }

        return this;
    } 
}
```

thx für deine unterstützung


----------



## Supersimsonfahrer (29. Jan 2006)

in 101 wäre die entsprechende zeile


----------



## Timmah (29. Jan 2006)

```
for (int i=0; i<9; i++) {
          tabelle.getColumnModel().getColumn(i).setCellRenderer(renderer);
      }
```

Das machst du weg, und ersetzt es durch


```
tabelle.setDefaultRenderer(Object.class, renderer);
```

Da du ja mehrere Zellen einfärben willst, würde ich an der Stelle, wo du das prüfst, in ein 2-dim boolean-Array die Spalten speichern, die du einfärben willst, und das Array dann an den Konstruktor der MyTableCellRenderer Klasse übergeben (musst du noch anpassen).
Dann fügst du in dem Renderer eine Abfrage dementsprechend ein; also so in etwa:


```
private boolean einfaerben[][] = new boolean[9][9];
```

Dann, wenn du die Zelle färben willst, setzt du die auf true.
Im Renderer sieht das dann so aus:


```
if (einfaerben[row][column] == true)
			{
				setForeground(Color.RED);

			}
			else
			{
				setForeground(Color.BLACK);

			}
```


----------



## Supersimsonfahrer (30. Jan 2006)

OK jetzt funzt es; so halb zumindest.

Wahrscheinlich hat es schon nach dem 5.Post funktioniert
aber ich hab es nicht gemerkt, weil ich das fenster nach dem button-klick immer erst minimieren muss
und dann wieder herstellen, das die Farbänderung sichtbar werden.

wie kann ich das automatisiert machen?
mit nem repaint oder so?

Gruß und Danke


----------



## Timmah (30. Jan 2006)

Timmah hat gesagt.:
			
		

> Also an dem Punkt, wo du die Zellenfarbe ändern willst, rufst du die setDefaultRenderer() Methode auf. In diesem Moment wird diese aufgerufen, in die Klasse MyTableCellRenderer gesprungen, und der Code dort ausgeführt.
> 
> Falls er da nicht reinspringt, hast du, wie soll es anders sein, irgendwas falsch gemacht
> 
> ...



Also musst du erst die Daten neu hinzufügen, damit der Renderer aufgerufen wird; geht bestimmt auch eleganter


----------

