# JTable inkl. JCheckbox



## b3n4kh (18. Okt 2011)

Hallo Leute!

Ich habe ein JTable in welchen ich in der 1. Spalte eine JCheckbox (mit custon cellrenderer und editor) habe, nun möchte ich mit deselektieren eben dieser Checkbox die Zeile "deaktivieren" - damit meine ich sowohl editable auf false setzen als auch die Hintergrundfarbe mit einem CellRenderer auf grau zu ändern!


Wie ihr euch schon denken könnt funktioniert das nicht so ganz wie ich möchte!

Mein Problem ist das wenn ich nun das die Checkbox zwar angezeigt wird aber sich die Farbe der anderen Zellen nicht ändert.


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


                if(CheckBoxCellEditor.isDisabled())
                {
                    cell.setBackground(Color.gray);
                }
               else
               {
                      cell.setBackground(Color.white);
              }
                
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        return cell;
    }
}
```

CheckBoxCellEditor schaut wie folgt aus:


```
class CheckBoxCellEditor extends AbstractCellEditor implements TableCellEditor
{

    static JCheckBox checkBox;
    
    public static boolean isDisabled()
    {
        if(checkBox.isEnabled())
            return false;
        
        return true;
    }

    public CheckBoxCellEditor()
    {
        checkBox = new JCheckBox();
        checkBox.setHorizontalAlignment(SwingConstants.CENTER);
        checkBox.setBackground(Color.white);

    }


    public Component getTableCellEditorComponent(
            JTable table,
            Object value,
            boolean isSelected,
            int row,
            int column)
    {

        checkBox.setSelected(((Boolean) value).booleanValue());

        return checkBox;
    }

    public Object getCellEditorValue()
    {
        return Boolean.valueOf(checkBox.isSelected());
    }
}
```


Meine erste Lösungsidee wäre ja gewesen:

Einen ChangedStateListener an die CheckBox zu hängen welche bei click eben bei click den Renderer 2. Renderer iwie bzw den Table updatet nur das hab ich mit "updateUI" eben nicht hinbekommen.


Ich bin für jegliche art von hilfe / links (google schon seit etlichen stunden an dem ding herum)
sehr sehr dankbar!!


----------



## Xeonkryptos (18. Okt 2011)

validate

Das sorgt dafür, dass Änderungen an einer angezeigten GUI auch geändert werden.


----------



## b3n4kh (18. Okt 2011)

Xeonkryptos hat gesagt.:


> validate
> 
> Das sorgt dafür, dass Änderungen an einer angezeigten GUI auch geändert werden.




Das hat leider nicht funktioniert, ich habe das ganze jetzt nocheinmal komplett durchgedacht und bin dem Fehler glaub ich so ziemlich auf die schliche gekommen, 

es funktioniert nun insoweit das wenn ich im ActoinEvent der CheckBox den TableListener setze:


```
class CheckBoxCellEditor extends AbstractCellEditor implements TableCellEditor
{

    static JCheckBox checkBox;

    public CheckBoxCellEditor()
    {
        checkBox = new JCheckBox();
        checkBox.setHorizontalAlignment(SwingConstants.CENTER);
        checkBox.setBackground(Color.white);
        checkBox.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e)
            {
                AlertView.grayout(checkBox.isEnabled());
               AlertView.table.validate();
            }
        });

    }
......   // Rest der CheckBox Klasse



    //Dies ist innerhalb der GUI HauptKlasse


    public static void grayout(boolean CheckboxSelektiert)
    {
        if (CheckboxSelektiert)
        {
            table.getColumnModel().getColumn(1).setCellRenderer((new CustomTableCellRenderer()));
            table.getColumnModel().getColumn(2).setCellRenderer((new CustomTableCellRenderer()));
            table.getColumnModel().getColumn(3).setCellRenderer((new CustomTableCellRenderer()));
            table.getColumnModel().getColumn(4).setCellRenderer((new CustomTableCellRenderer()));
        }
        else
        {
            table.getColumnModel().getColumn(1).setCellRenderer((new DefaultTableCellRenderer()));
            table.getColumnModel().getColumn(2).setCellRenderer((new DefaultTableCellRenderer()));
            table.getColumnModel().getColumn(3).setCellRenderer((new DefaultTableCellRenderer()));
            table.getColumnModel().getColumn(4).setCellRenderer((new DefaultTableCellRenderer()));
        }
    }
```

Dann setzt er mir die Farbe NUR wenn ich mit der maus irgendwo in den table klicke!! (zumindest tut er es jetzt iwie)
Jedoch auch mit validate hilft leider nicht...


Wie bekomme ich das hin das sich die Farbe einfach beim selektiern des Buttons ändern bzw wie kann die Hintergrund Farbe einzelner JTable Row's nach einem Event trigger ändern??


----------



## hdi (18. Okt 2011)

Uff.. Gewöhn' dir diese statischen Variablen ab. Da kann alles oder nichts aus jedem erdenklichen Kontext heraus zugreifen. So kann man die Logik nur sehr schwer nachvollziehen. Statische Variablen sind nur in wenigen Fällen sinnvoll. In deinem nicht.



> Wie bekomme ich das hin das sich die Farbe einfach beim selektiern des Buttons ändern bzw wie kann die Hintergrund Farbe einzelner JTable Row's nach einem Event trigger ändern??


Versuch mal ein 
	
	
	
	





```
JTable#repaint()
```
. Aber vllt liegt der Fehler im Renderer selbst, bzw dieser (statischen ) CheckDingsBumsKlasse da..


----------



## Michael... (19. Okt 2011)

Wenn ich das richtig verstehe, dann hat eine Änderung in der ersten Spalte Auswirkungen auf die gesamte Zeile. Daher müsste das TableModel dafür eigentlich ein anderes TabelModelEvent abfeuern, das behauptet, die ganze Zeile habe sich geändert.

Meiner Meinung ist ein TableCellEditor mit nur einer CheckBox unnötig. Einen CheckBoxRenderer besitzt die JTable standardmäßig - man muss es ihr nur über das Model "sagen", dass es sich hier um einen boolean handelt. siehe: 
	
	
	
	





```
public Class<?> getColumnClass(int column)
```
Um ganze Zeilen zu "markieren" überschreibe ich oft die perpareRenderer der JTable.
Grundsätzlich macht es keinen Sinn ein und denselben Renderer oder Editor mehrfach zu erstellen, um diese mehreren Spalten zu zuweisen.

Hier mal ein schnell hingeschriebens Beispiel, wie ich die Anforderung verstanden habe:

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

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TableCheckBoxDemo extends JFrame {
	DefaultTableModel model;
	
	public TableCheckBoxDemo() {
		model = new DefaultTableModel(new Object[][] {{true, "Inhalt A"}, {false, "Inhalt B"}, {true, "Inhalt C"}}, new String[] {"aktiv", "Titel"}) {
		    public boolean isCellEditable(int row, int column) {
		    	if (column  >0) {
		    		return Boolean.parseBoolean(this.getValueAt(row, 0).toString());
		    	}
		        return true;
		    }
		    
		    public Class<?> getColumnClass(int column) {
		    	if (column==0)
		    		return Boolean.class;
		    	return super.getColumnClass(column);
		    }
		    
		    public void setValueAt(Object value, int row, int column) {
		    	super.setValueAt(value, row, column);
		    	if (column==0)
		    		this.fireTableRowsUpdated(row, row);
		    }
		};
		
		JTable table = new JTable(model) {
			 public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
				Component c = super.prepareRenderer(renderer, row, column);
				if (Boolean.parseBoolean(this.getValueAt(row, 0).toString()))
					c.setBackground(Color.WHITE);
				else
					c.setBackground(Color.GRAY);
				return c;
			}
		};
		
		this.add(new JScrollPane(table));
	}
	
	public static void main(String[] args) {
		JFrame frame = new TableCheckBoxDemo();
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
```


----------



## b3n4kh (19. Okt 2011)

Danke, danke danke für die ganze hilfe 

@Michael, genau das war mein 1. ansatz, also 
	
	
	
	





```
public Class<?> getColumnClass(int column)
```
 jedoch habe ich (wie ich jetzt nachträglich nach vergleicher meines alten und deinen Codes) gesehn das ich den prepareRenderer falsch implementiert habe !!

Es funktioniert jetzt,


----------

