# JComboBox mit CellRenderer (Auswahl)



## goodcat (19. Jan 2012)

Hi,

ich habe eine JComboBox mit einem CellRenderer:


```
import java.awt.Component;

import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;


@SuppressWarnings("serial")
public class CustomerCellRenderer extends JLabel implements ListCellRenderer<Customer> {

    public Component getListCellRendererComponent( JList list, Customer value, int index, boolean isSelected, boolean cellHasFocus ) {
    	
    	if ( isSelected ) {
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }
    	
        if( value instanceof Customer ) {
//            Customer kunde = (Customer) value;
            setText(value.getName());
        } 
        else {
            setText("");
        }
        
        return this;
    }  

	
}
```

Mein Problem ist das die Selection fehlt. Also wenn ich die ComboBox öffne und einen Eintrag auswählen möchte wird er nicht mit einem blauen Hintergrund hinterlegt sondern die Schrift wird weiß. Habe es auch schon mit Color.BLACK und Color.BLUE probiert.. ohne Erfolg

Hat da jemand eventuell einen Tipp für mich?


----------



## Marco13 (19. Jan 2012)

Hab's jetzt nicht im Detail nachvollzogen, nur ein schneller Tipp: Wenn man vom DefaultCellRenderer (oder wie der heißt) erbt, kann man bei diesem Aufruf einfach schreiben

```
super.getCellRendererGedöhns(...der ganze kram...);
this.setText(meinSpeziellerText);
return this;
```
Dann wird beim super-Aufruf alles so "eingestellt", wie es Standard ist, und danach kann man seinen speziellen Text reinlegen.


----------



## hdi (20. Jan 2012)

Die Sache mit der Hintergrundfarbe funktioniert nicht, da ein JLabel standardmäßig nicht opaque ist. Das kannst du mit einem entsprechenden Setter umstellen:


```
public class CustomerCellRenderer extends JLabel implements ListCellRenderer<Customer> {

    {
        this.setOpaque(true);
    }

    // ...
}
```

PS: Auf blöd hab ich das jetzt auch genau falsch rum gesagt. Ich weiß es grad selbst nicht genau. Auf jeden Fall entweder setOpaque(true) oder setOpaque(false) dann sollte es gehen


----------



## jgh (20. Jan 2012)

war schon genau richtig. Der Defaultwert bei allen JComponents ist [c]false[/c] => Ein JLabel zeigt neben dem Text nichts weiteres an, ist also durchsichtig, oder nicht deckend.


----------



## Gast2 (20. Jan 2012)

Wie es Marco sagte ist es am einfachsten

```
public class MyCellRenderer extends DefaultListCellRenderer{
	
	  @Override
	public Component getListCellRendererComponent(JList list, Object value,
			int index, boolean isSelected, boolean cellHasFocus) {
		JLabel jLabel  = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected,
				cellHasFocus);
		jLabel.setText("Hallo Welt");
		return jLabel;
	}
	  
  }
```


----------



## Michael... (20. Jan 2012)

... und den Cast kann man sich in diesem Fall sparen

```
public class MyCellRenderer extends DefaultListCellRenderer {
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
			super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
			setText("Hallo Welt");
			return this;
		}
	}
```


----------



## goodcat (20. Jan 2012)

Jau vielen Dank für den Tipp. 

```
setOpaque(true);
```
hat wunderbar funktioniert.

Nochmal zu dem Renderer und dem cast bzw. den Code der hier gepostet wurde:

```
public class MyCellRenderer extends DefaultListCellRenderer {
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            setText("Hallo Welt");
            return this;
        }
    }
```

Würde den Code gern benutzen, aber ich muss doch auf meine Klasse casten um auf die Methode .getName() zugreifen zu können um den Namen zu bekommen.
Ich habe sonst 6 Renderer für 6 ComboBoxen .. Is n bissl heavy!

In meinem ersten Post habe ich den Code von meinem Renderer... Meint ihr man könnte den so allgemein wie möglich halten um nur 1 Renderer zu haben? bzw. wie soll das mit dem geposteten Code funktionieren?


----------



## Marco13 (20. Jan 2012)

Ist nicht ganz klar was du meinst... Verschiedene Klassen? Oder nur mehrere Instanzen?


----------



## vanny (21. Jan 2012)

Wenn ich dich richtig verstehe, dann bietet sich ein Interface oder eine abstrakte Klasse an, die die Methode getName(); erzwingt.

Dann kannst du über den abstrakten Datentyp mit nur einem CellRenderer arbeiten.

Gruß Vanny


----------



## goodcat (21. Jan 2012)

Hi,

ich habe es momentan so gelöst:

```
@SuppressWarnings("serial")
public class CellRenderer extends JLabel implements ListCellRenderer<Object> {

    public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) {    	
    
    	setOpaque(true);
    	
    	if ( isSelected ) {
            setBackground( list.getSelectionBackground() );
            setForeground( list.getSelectionForeground() );
        } else {
            setBackground( list.getBackground() );
            setForeground( list.getForeground() );
        }
    	
        if( value instanceof Customer ) {        	
        	Customer customer = (Customer) value;
        	if ( customer.getCompany() == null || customer.getCompany().isEmpty() ) {
        		setText(customer.getName());
        	} 
        	else {
        		setText(customer.getCompany());
        	}            
        }
        else if ( value instanceof ContactPerson ) {
        	ContactPerson contactPerson = (ContactPerson) value;         	
        	setText(contactPerson.getName());
        }
        else if ( value instanceof Reviser ) {
        	Reviser reviser = (Reviser) value;         	
        	setText(reviser.getName());
        }
        else if ( value instanceof Support ) {
        	Support support = (Support) value;         	
        	setText(support.getName());
        }
        else {
            setText("");
        }
        
        return this; 
        
    }  
	
}
```

Wenn ich ein Interface implementiere dann habe ich dann nicht immernoch das Problem das ich casten muss?


----------



## vanny (21. Jan 2012)

Nö, zumind nicht, wenn es um gleiche Methoden wie zBsp. getName() geht.

Wenn alle dein Interface "Renderable" (nur ein Beispiel ) implementieren, dann kannst du ja value in den Datentyp Renderable casten und davon dann die getName(); ansprechen.
Schlüsselwort "Abstrahieren, Polymorphie"

Gruß Vanny


----------



## Marco13 (21. Jan 2012)

Hm... Sind diese verschiedenen Objekte in verschiedenen JComboBoxes, oder alle in einer? Wenn es verschiedene sind, könnte man da IMHO schon mehrere Klassen machen (oder ein gemeinsames interface definieren, aber der Customer wäre immernoch ein Spezialfall)


----------

