Search code examples
javalinuxswinggtkjcombobox

Java JComboBox Custom Renderer and GTK


I have a list of Customer objects that I need to have selectable from a JComboBox. From what I read I need to implement a custom renderer to have the fields I want displayed in the list.

I want my JComboBox to have entries formatted as such:

+----------------------------------------------+
|  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    |
+----------------------------------------------+

I used this code:

public class CustomerListCellRenderer extends 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;
  }
}

This doesn't work correctly under Solaris / Unix / Linux using the system GTKLookAndFeel. The background of the input area of the combobox is not drawn and no border is drawn around it. (See screenshot below). Is there another way to achieve this that will work correctly across the 3 major platforms (Win/Mac/GTK)? Can I do a converter to do this and only manipulate the data not the GUI?

My current workaround is to override toString() on my Customer object to display each record in the format I want, but looking for other ideas.

alt text

Nick


Solution

  • Same issue, I did this in order to customize it for showing icons:

    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;
        }
    }
    

    Then assigned the renderer like this:

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

    This has worked out fine for me, so far.