2009-06-25 7 views
0

J'ai une liste d'objets Customer que je dois avoir sélectionnable à partir d'un JComboBox. D'après ce que j'ai lu, j'ai besoin d'implémenter un moteur de rendu personnalisé pour avoir les champs que je veux afficher dans la liste.Java Renderer personnalisé JComboBox et GTK

Je veux que mon JComboBox d'avoir des entrées formatées en tant que tel:

+----------------------------------------------+ 
| Customer Name - Contact - City, State V | 
+==============================================+ 
| Customer #2 Name - Contact - City, State | 
| Customer #3 Name - Contact - City, State | 
| Customer #4 Name - Contact - City, State | 
| Customer #5 Name - Contact - City, State | 
+----------------------------------------------+ 

J'ai utilisé ce code:

CustomerListCellRenderer public class étend DefaultListCellRenderer {

@Override 
public Component getListCellRendererComponent(
     JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
    super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
    if (value instanceof Customer) { 
     Customer c = (Customer) value; 

     StringBuffer sb = new StringBuffer(); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getCompany()); 
     } 
     sb.append(" - "); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getContact()); 
     } 
     sb.append(" - "); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getCity()); 
      sb.append(", "); 
     }    
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getState()); 
     } 

     setText(sb.toString()); 
    } 
    return this; 
    } 
} 

Cela ne fonctionne pas correctement sous Solaris/Unix/Linux en utilisant le système GTKLookAndFeel. L'arrière-plan de la zone d'entrée de la zone de liste déroulante n'est pas dessiné et aucune bordure n'est dessinée autour de celle-ci. (Voir la capture d'écran ci-dessous). Existe-t-il un autre moyen d'y parvenir qui fonctionnera correctement sur les 3 plateformes majeures (Win/Mac/GTK)? Est-ce que je peux faire un convertisseur pour faire ceci et manipuler seulement les données pas l'interface graphique?

Ma solution de contournement actuelle consiste à remplacer toString() sur mon objet Customer pour afficher chaque enregistrement au format souhaité, mais en recherchant d'autres idées.

alt text http://i40.tinypic.com/5dw1hd.jpg

Nick

+0

Je ne vois pas pourquoi vous auriez besoin d'un moteur de rendu personnalisé pour cet exemple. –

+1

@ammoQ: Vous en avez besoin car vous voulez stocker un client dans votre ComboBoxModel, et non une chaîne. Ainsi, lorsque vous faites: getSelectedItem(), vous obtenez un client, et non un String. –

Répondre

2

Même problème, je l'ai fait afin de le personnaliser pour montrer les icônes:

private static class CustomComboBoxRenderer extends DefaultListCellRenderer 
{ 
    private final ListCellRenderer backend; 

    public CustomComboBoxRenderer(ListCellRenderer backend) 
    { 
     this.backend = backend; 
    } 

    @Override 
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) 
    { 
     Component component = backend.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
     if(component instanceof JLabel == false) 
      component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
     JLabel label = (JLabel)component; 
     label.setIcon(Icons.COMPONENT); 
     return label; 
    } 
} 

assignés Puis le moteur de rendu comme celui-ci:

comboBox.setRenderer(new CustomComboBoxRenderer(comboBox.getRenderer())); 

Cela a fonctionné bien pour moi, à ce jour .

0

Le DefaultListCellRenderer étend JLabel et ressemble JLabel. Si vous avez un ComboBox non modifiable, alors le Renderer retourné via getRenderer est utilisé pour peindre la zone de liste déroulante et également pour la zone "input". Essayez de jouer avec les paramètres bordure/premier plan/arrière-plan pour ComboBox et le moteur de rendu.

1

Essayez ceci:

public Component getListCellRendererComponent(
     JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
    if (value instanceof Customer) { 
     Customer c = (Customer) value; 

     StringBuffer sb = new StringBuffer(); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getCompany()); 
     } 
     sb.append(" - "); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getContact()); 
     } 
     sb.append(" - "); 
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getCity()); 
      sb.append(", "); 
     }    
     if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getState()); 
     } 

     value = sb.toString(); 
    } 
    return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
    } 
} 

Utiliser aussi un StringBuilder pas StringBuffer (ce qui est une situation unique filetée).

également aussi il semble que vous avez couper et coller des erreurs dans le code par exemple:

 if (c.getCompany() != null && c.getCompany().length() > 0) { 
      sb.append(c.getState()); 
     } 

vérifie la société membre et en utilisant l'État membre.