# JTable CellRenderer über boolean



## freez (1. Apr 2005)

Hallo,

ich habe euer sehr gutes Tutorial über JTable gelesen. Nun wollte ich natürlich das für mein eigenes Projekt nutzen. Ich möchte gern die Checkbox an manchen stellen ausblenden, wenn die Spalte den Typ Boolean hat. Folgenden Code habe ich:

```
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
	{		
		if(value instanceof Boolean)
		{
			JLabel lbl = new JLabel("Hallo");
			return lbl;
		}
		return new JLabel(value.toString());
	}
```
Stört euch nicht daran, daß es so erst mal keinen Sinn ergibt alle Checkboxen mit einem JLabel("Hallo") zu überschreiben. Es ist nur ein Test, und soll später nur auf einzelne Zellen angewant werden. Und zwar mit einem leeren JLabel(""). Das Ziel ist es an bestimmten Stellen die Checkbox einfach auszublenden.

Er blendet mir aber nichts weg. Alle Checkboxen bleiben. Im Tutorial funktioniert es. nur finde ich den Unterschied nicht. dort werden die Checkboxen durch yes oder no überschrieben (
http://www.java-forum.org/de/viewtopic.php?t=7708 )

Oder gibt es vielleicht noch einen anderen Weg die Checkboxen auszublenden?

Hier noch mein TableModel:

```
public class JCheckboxTableModel extends AbstractTableModel
{
	String [] fileNames;
	String [] fullPath;
	boolean [] toDownload;
	int [] positions;
	
	/**
	 * @param fileNames
	 * @param fullPath
	 * @param toDownload
	 * @param positions
	 */
	public JCheckboxTableModel(String[] fileNames, String[] fullPath,
					boolean[] toDownload, int[] positions)
	{
		super();
		this.fileNames = fileNames;
		this.fullPath = fullPath;
		this.toDownload = toDownload;
		this.positions = positions;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getColumnCount()
	 */
	public int getColumnCount()
	{
		return 3;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getRowCount()
	 */
	public int getRowCount()
	{
		return fileNames.length;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getValueAt(int, int)
	 */
	public Object getValueAt(int rowIndex, int columnIndex)
	{	
		switch( columnIndex )
		{
        case 0: if(fileNames[ rowIndex ] != null && rowIndex < fileNames.length)
        			return new String(fileNames[ rowIndex ]); break;
        case 1: if(rowIndex < toDownload.length)
        			return new Boolean( toDownload[ rowIndex ] ); break;
        case 2: if(fullPath[ rowIndex ] != null && rowIndex < fullPath.length)
					return new String(fullPath[ rowIndex ]); break;
        default: return null;
		}
		return null;

	}
    // Eine Angabe, welchen Typ von Objekten in den Columns angezeigt werden soll
    public Class getColumnClass(int columnIndex) {
       switch( columnIndex ){
          case 0: return String.class;
          case 1: return Boolean.class;
          case 2: return String.class;
          default: return null;
       }
    }
    // nur die 2. Spalte darf editiert werden
	public boolean isCellEditable(int rowIndex, int columnIndex) 
	{
		if(columnIndex == 1)
			return true;
		else 
			return false;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
	 */
	public void setValueAt(Object aValue, int rowIndex, int columnIndex)
	{
		switch( columnIndex )
		{
		case 0: if(fileNames[ rowIndex ] != null && rowIndex < fileNames.length)
					fileNames[ rowIndex ] = ((String )aValue).toString(); break;
		case 1: if(rowIndex < toDownload.length)
					toDownload[ rowIndex ] = ((Boolean)aValue).booleanValue(); break;
		case 2: if(fullPath[ rowIndex ] != null && rowIndex < fullPath.length)
					fullPath[ rowIndex ] = ((String )aValue).toString(); break;
		default: return;	        
		}
	}
    
	// Die Titel der einzelnen Columns
    public String getColumnName(int column) {
       switch( column ){
          case 0: return "FileName";
          case 1: return "Download?";
          case 2: return "komplette Adresse";
          default: return null;
       }
    }
}
```

Vielen Dank schon mal im vorraus.


----------



## Roar (1. Apr 2005)

freez hat gesagt.:
			
		

> ich habe euer sehr gutes Tutorial über JTable gelesen.





> return new JLabel(value.toString());



das widerspricht sich aber...

hast du deiner tabelle den renderer auch gesetzt? :?


----------



## freez (1. Apr 2005)

Hm, eins habe ich schon herrausgefunden. in meinem Renderer springt er in die IF Abfrage nicht rein. Wieso auch immer. Aber durch die letzte return Zeile müßte er doch sowieso ein JLabel anzeigen, statt einer CheckBox, oder?


----------



## Roar (1. Apr 2005)

Roar hat gesagt.:
			
		

> hast du deiner tabelle den renderer auch gesetzt? :?


 :?:


----------



## freez (1. Apr 2005)

Das stimmt: normalerweise sollte man ableitet. In meiner ersten Version habe ich aber mit noch anderen Komponenten gearbeitet, die ich zurückgeben wollte (z.B. JPane mit Image). Somit war das in dem Moment nicht sinnvoll (meine ich jedenfalls). Wenn es bei dem Label bleibt mache ich das natürlich so. Ist ja schöner 

So, hier mal zu deiner Frage:

```
public class JCheckboxTable extends JTable
{
	JCheckboxTableModel model;
	JCheckboxTableRenderer renderer;

	/**
	 * @param fileNames
	 * @param toDownload
	 * @param fullNames
	 * @param positions
	 */
	public JCheckboxTable(String[] fileNames, boolean[] toDownload, String[] fullNames, int[] positions)
	{
		model = new JCheckboxTableModel(fileNames,fullNames,toDownload,positions);
		int maxLength = 0;
			for(int i = 0; i < fileNames.length; i++)
				if(fileNames[i].length() > maxLength)
					maxLength = fileNames[i].length();
				
		renderer = new JCheckboxTableRenderer(positions, maxLength);
		this.setModel(model);		
		this.setDefaultRenderer(Object.class, renderer);
		this.setShowGrid(false);
		
		
	}

	public static void main(String[] args)
	{
		String [] a = {"", "GIF", "", "a", "b", "", "JPG", "", "c", "d", "", "PNG", "", "e", "f", "g", "h"};
		String [] b = {"", "", "", "a", "b", "", "", "", "c", "d", "", "", "", "e", "f", "g", "h"};
		boolean [] c = {false,true,false,true,true,false,true,false,true,true,false,true,false,true,true,true,true};
		int [] d = {0, 5, 10};
		JCheckboxTable table = new JCheckboxTable(a, c , b, d);
		JFrame frame = new JFrame("TITEL");
		frame.getContentPane().add(new JScrollPane(table));
		frame.setVisible(true);
		frame.pack();
	}
}
```

Obwohl, ich sehe gerade, wenn ich nur die Booleans ändern will, könnte ich beim DefaultRenderer ja Boolean.class angeben ... das probiere ich als nächstes


----------



## freez (1. Apr 2005)

So, das Problem lüftet sich. setze ich den Default Renderer auf Boolean.class funzt es. Wieso geht es nicht mit Object.class?


----------



## Beni (2. Apr 2005)

Weil es einen DefaultRenderer für Boolean gibt.

Wenn die Tabelle die Klasse einer Spalte abfragt, geht sie den Vererbungsbaum hoch, und guckt, ob es da einen entsprechenden Renderer gibt. Wenn sie ein Boolean.class bekommt, gibt es gleich bei "Boolean" einen Eintrag (die Tabelle selbst generiert einen Renderer für Boolean's), und "Object" wird gar nicht erst abgefragt.


----------



## Guest (2. Apr 2005)

Eine Anmerkung zwischendurch, da mir schlecht wird, wenn ich sowas sehe... 

*Erstelle das Label-Objekt (oder was auch immer) nicht in der Methode "getTableCellRendererComponent(...)"*
Die Methode wird u.U. zig mal in der Sekunde aufgerufen, wodurch auch hunderte von Labels erstellt werden.
Klartext: Wiederverwenden, statt immer wieder neu Instanzieren.


----------



## freez (2. Apr 2005)

Hallo Beni,

wieso funktioniert es dann im Tutorial. Dort wurde auch Object.class angegeben und im Renderer dann abgefragt, was denn "value" eigentlich ist.
Mein Problem ist, daß ich je nach Zelle andere Objekte dort einfügen möchte. zB. eine Grafik, Ein JLabel usw. Somit ging ich nach dem Tutorial und habe Object.class angegeben. Ich will ja jede Zelle einzeln im Renderer bearbeiten.

@Gast: Danke, auf die Idee bin ich gar nicht gekommen. Natürlich werde ich es dann in der final Version entsprechend machen


----------



## Roar (2. Apr 2005)

freez hat gesagt.:
			
		

> @Gast: Danke, auf die Idee bin ich gar nicht gekommen. Natürlich werde ich es dann in der final Version entsprechend machen



steht aber im tutorial :-O


----------



## Beni (2. Apr 2005)

freez, es gibt einen Unterschied zwischen deinem TableModel, und dem TableModel in dem Tutorial:
Das Model im Tutorial gibt für jede Spalte als Klasse "Object.class" an:

```
public Class getColumnClass(int columnIndex) {
         return Object.class;
      }
```

Dein Model hingegen gibt auch andere Klassen an:

```
public Class getColumnClass(int columnIndex) {
       switch( columnIndex ){
          case 0: return String.class;
          case 1: return Boolean.class;
          case 2: return String.class;
          default: return null;
       }
    }
```

Das JTable im Tutorial guckt immer als erstes nach, ob es einen Renderer für "Object" gibt, und ja, es gibt einen (der wurde ja extra registriert).
Bei deinem Code hingegen wird zuerstmal nachgeschaut, ob es z.B. was für "Boolean" gibt (und ja, es gibt was. Automatisch vom JTable hergestellt).


----------



## freez (2. Apr 2005)

Ich weiss  Aber bei mir war der Ansatz wegen den Verschiedenen Objekten, die ich zurückgeben will und nur von einem erben kann. Im Tutorial war ja das Beispiel mit dem Label und da wurde ja this zurückgegeben. Deswegen habe ich nicht daran gedacht die ausserhalb zu instanziieren. Es war auch mein erster Versuch ... Verzeiht mir meine anfängerfehler 

Tja, das Problem hat sich zwar etwas gelüftet, aber wie kann ich alle Zellen mit einem Renderer bearbeiten. Das Problem ist weiterhin da, daß ich die Checkboxen nicht ausblenden kann (Also, daß mir ein leeres Label gezeichnet wird, statt einer Checkbox).


----------



## freez (6. Apr 2005)

So, ich habe es nun folgendermaßen gelöst,


```
public JCheckboxTable(String[] fileNames, boolean[] toDownload, String[] fullNames, int[] positions)
{
	model = new JCheckboxTableModel(fileNames,fullNames,toDownload,positions);
	int maxLength = 0;
		for(int i = 0; i < fileNames.length; i++)
			if(fileNames[i].length() > maxLength)
				maxLength = fileNames[i].length();
			
	renderer = new JCheckboxTableRenderer(positions, maxLength);
	this.setModel(model);		
	this.setDefaultRenderer(Object.class, renderer);
	this.setDefaultRenderer(Boolean.class, renderer);
	this.setShowGrid(false);	
}
```

@Beni: natürlich hast du recht ... habe an dem Abend net ganz kapiert, was du wolltest ... sorry

Ich habe jetzt einfach einen 2. DefaultRenderer für Boolean gesetzt. Und JLabel und JCheckbox habe ich nun auch ausserhalb vom cellRenderer erstellt (wiederverwenden statt neu erstellen ).

Noch ein Tip: vom JLabel setOpaque(true) setzten, damit die Hintergrundfarbe von JLabel angezeigt wird. Das war auch noch ein kleines Problem bei mir 

Also, vielen Dank für die Hilfe ... war echt informativ


----------

