# Image und Text in einer List anzeigen



## Paladin (2. Feb 2004)

Hi,

ich möchte gerne ein Image und einen Text in einer List anzeigen. Das soll praktisch so eine art
Userliste werden bei der immer zuerst ein Symbol steht und dahinter der Name.

Hat jemand ne Ahnung wie das geht?

Gruß

Paladin


----------



## Andre1002 (2. Feb 2004)

Hallo,

Du schreibst einen eigenen CellRenderer, der mit 
	
	
	
	





```
setCellRenderer(new MyListCellRenderer())
```
 in Deiner Liste gesetzt wird.
Ein CellRenderer könnte etwa so aussehen:


```
public class MyListCellRenderer extends JCheckBox implements ListCellRenderer{
    public Component getListCellRendererComponent(JList list,
                  Object value, int index, boolean isSelected, boolean cellHasFocus)
    {
           //je nach Selektion die Farbe setzen
      setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
      setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
      try{
        MyObjekt obj = (MyObjekt)value;    //MyObjekt ist der Container für einen User in Deinem Fall
        setText(obj.getName());              //der Text der in der Liste angezeigt werden soll
        Icon i = obj.getIcon();             //das zu setzende Icon...
        this.setIcon(i);                //...wird hier gesetzt
      }
      catch(Exception ex){
        ex.printStackTrace();
      }
      setFont(list.getFont());
      setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));

      return this;
    }
}
```

probier mal ob's funktioniert...

Andre1002


----------



## Paladin (9. Feb 2004)

Hi Andre,

das klappt sehr gut mit dem CellRenderer solange man nicht für verschiedene User
verschiedene Icons/Texte benutzen möchte.
Hast du eine Ahnung wie man je nach User ein anderes Logo/einen anderen Text setzen kann?


Gruß

Paladin


----------



## Andre1002 (9. Feb 2004)

Hallo Paladin,

wenn Du Deiner Liste immer wieder pro Userzeile eine neue Instanz deines Objektes addierst und dieses Objekt ein spezielles Icon erhält, dann wird vor jede auch immer das richtige Icon gezeichnet.

Ich hoffe dass ich Dich richtig verstanden habe...

Andre1002


----------



## Paladin (10. Feb 2004)

Hi Andre,

das leuchtet mir ein nur ich weiss nicht was für ein Objekt ausser dem Vektor
Text und ein Bild aufnehmen kann.

Mit einem Vektor klappt das schonmal nicht weil die JList einen Vektor nur per .setListData(Vektor) akzeptiert und mit diesem Befehl werden alle anderen Einträge gelöscht.
JList.add(Vektor) ist soweit ich weiss nicht möglich (jedenfalls meckert eclipse wenn ich das machen will).

Kannst du mir vielleicht ein kurzes Beispiel geben wie man der JList mittels einem Object Zeilen hinzufügt?

Gruß

Paladin


----------



## Andre1002 (10. Feb 2004)

Hallo Paladin,

erstelle Dir doch einfach ein Objekt was Text und Bild aufnehmen kann:


```
public class MyObject {
    private Icon icon = null;
    private String text = "";
    
    public void setIcon(Icon aIcon){
      icon = aIcon;
    }
    public Icon getIcon(){
      return icon;
    }
    public void setText(String aText){
      text = aText;
    }
    public String getText(){
      return text;
    }
    public String toString(){
      return text;
    }
}
```

Die Instanzen des Objektes addierst Du dann Deiner Liste. Ob Du dann mit JList.setListData(Object[]) oder ob Du Deine Objekte in einem Vector sammelst oder mit einem DefaultListModel arbeitest dürfte dann egal sein.

Gruß

Andre1002


----------



## Beni (10. Feb 2004)

Paladin hat gesagt.:
			
		

> JList.add(Vektor) ist soweit ich weiss nicht möglich (jedenfalls meckert eclipse wenn ich das machen will).


Weils dort eine Component erwartet?

Aber der Vector könnte schon funktionieren, er muss einfach weitere Vectors enthalten  :wink: 
Dann kommt diese *hässliche* Variante raus.


```
Vector data = new Vector();
Vector entry = new Vector();
data.add( entry );
entry.add( icon );
entry.add( text );

Object cellValue = ((Vector)((Vector)data).get( row )).get( column );
```

Nicht allzu ernst nehmen, die Lösung von Andre1002 ist 100 mal schöner.

mfg Beni


----------



## Paladin (10. Feb 2004)

Hi Andre,

das mit dem Objekt ist mir klar. 
Ich erstelle also ein Array von diesem Objekt und schicke das ganze dann mit .setListData an den Renderer.
Allerdings gibt der Renderer jetzt in meiner Liste nichts mehr aus und ich verstehe nicht was an meiner
Version falsch ist. Nachfolgend schreibe ich mal einen kleinen Programmablaufplan damit du - wenn du noch
Geduld für meine Probleme hast - sehen kannst was ich (falsch) mache.

*1. Klasse UserData*
Ich habe eine Klasse mit namen UserData erstellt. Diese Klasse hat die Attribute String userName, String userPicture (Name der Bilddatei) und String userJob. + den get und set Methoden dazu.

*2. Einsetzen der Daten in eine Instanz von UserData*
In der Funktion welche die Userliste an die JList übergibt mache ich folgendes:

...

```
UserData user[] = new UserData[(m_client.userDataVektor.size()/4)+3]; 
//(m_client.userDataVektor.size()/4)+3 gibt die Zahl der benötigten Elemente an
...
user[0].setUserName("Alle");
user[0].setUserPicture("alle.gif");
user[0].setUserJob("");	
user[0].setUserAway(false);

//hier steht noch eine Schleife welche die User und ihre Daten in user[1], user[2] etc. einfügt.

m_client.ta_useronline.setListData(user);  //Werte in die Liste schreiben
```

*3. Der CellRenderer*
Ich schreibe hier mal den gesamten Code vom CellRenderer hin. Könnte ja sein, dass ich hier schon
irgendwo am Anfang murks gemacht habe.


```
class MyCellRenderer extends JLabel implements ListCellRenderer {
		
     public Component getListCellRendererComponent(
     JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
          UserData[] userData = (UserData[]) value;			
          icon = createImageIcon(String.valueOf(userData[index].getUserPicture()), "Bild");
          //createImageIcon(String dateipfad, String beschreibung) lädt die Bilddatei

          setIcon(icon);
          setText("(" + userData[index].getUserJob() + ")   " + userData[index].getUserName());		
          				
          return this;	
     }			
}
```


Das alles kompiliert einwandfrei und trotzdem bekomme ich in der JList nichts angezeigt (weder Text noch ein Bild).

Vielen Dank im voraus

Gruß

Paladin


----------



## Beni (10. Feb 2004)

Hallo Paladin

Ich hab deinen Code mal versucht nachzustellen, und bin auf ein leicht anderes Ergebnis gekommen.
Vielleicht hilft dir ein Vergleich:


```
// Etwas einfacher, ist ja auch nur ne Demo

public class UserData {
  private String name, job;
  public UserData( String name, String job ){
    this.name = name;
    this.job = job;
  }

  public String getName(){
    return name;
  }
  public String getJob(){
    return job;
  }
```


```
// Macht etwa dasselbe wie das Original

class Renderer extends JLabel implements ListCellRenderer {
  public Renderer(){
  }
  public Component getListCellRendererComponent( JList list, Object value, int index, boolean sel, boolean foc ){
    UserData u = (UserData)value;
    this.setText( u.getName() + " / " + u.getJob() );
    return this;
  }
}
```


```
public class ListTest extends JFrame{
  public ListTest() {
    JList list = new JList();

    UserData[] user = new UserData[3];
    user[0] = new UserData("Marie", "Köchin");
    user[1] = new UserData("Heinz", "Architekt");
    user[2] = new UserData("Fritz", "Wirt");

    list.setListData( user );      // Bis hier 1:1 Kopie von oben
    list.setCellRenderer( new Renderer() );  // Cell-Renderer setzen

    this.getContentPane().add( list );
    setBounds( 10, 10, 200, 200 );
    setDefaultCloseOperation( EXIT_ON_CLOSE );
    setVisible( true );
  }
}
```

Das funktioniert recht gut (zumindest hat es Text).

Aber wie Du siehst, haben wir einen recht grossen Unterschied im CellRenderer. Ich muss dort nie ein Array benutzen!
Im Gegenteil, das würde bei mir eine Exception verursachen. Deshalb meine Frage: Wird die Methode _getListCellRendererComponent_ bei Dir überhaupt aufgerufen ??

Gruss Beni

P.S. noch was: _icon = createImageIcon(String.valueOf(userData[index].getUserPicture()), "Bild"); _
Das solltest einmal machen, und in UserData oder sonst wo abspeichern. Wenn Du jedesmal beim Neuzeichnen der Liste ein Bild lädst, wird dein Progi nie sehr schnell werden. :wink:


----------



## Paladin (10. Feb 2004)

Hi Beni,

Beni:


> Wird die Methode getListCellRendererComponent bei Dir überhaupt aufgerufen ??



Wie mir gerade aufgefallen ist wird die Methode gar nicht aufgerufen aber das liegt
daran, dass ich bei der ausführung der folgenden Zeile eine NullPointer Exception bekomme:


```
user[0].setUserName("Alle"); 
user[0].setUserPicture("alle.gif"); 
user[0].setUserJob("");    
user[0].setUserAway(false);
```

Beni:


> Das solltest einmal machen, und in UserData oder sonst wo abspeichern. Wenn Du jedesmal beim Neuzeichnen der Liste ein Bild lädst, wird dein Progi nie sehr schnell werden.



Tja, jetzt wo du das sagst fällt mir auch auf, dass das vielleicht nicht der beste Weg ist   


Gruß

Paladin


----------



## Roar (10. Feb 2004)

den renderern musst du der list auch zuweiosen.
setDefaultRenderer() oder so ähnlich ist die methode => api  :### 
und dann musst du user[0] auch erstmal ein UserData object zuweisen.


----------



## Beni (10. Feb 2004)

@Roar

setCellRenderer  :!: 

Steht 2 Beiträge weiter oben, Quelltext lesen!  :###   :wink: 

mfg Beni


----------



## Paladin (10. Feb 2004)

Hi,

ich hab das Problem gefunden. Ich habe einfach mal folgendes in meiner Initialisierungsschleife vergessen:
   objekt = new Objekt();

Traurig aber wahr.   
Vielen Dank an Andre1002 und Beni für die Geduld die Ihr mit mir hattet.

Gruß

Paladin


----------

