Search code examples
javaswingjcomboboxpojolistcellrenderer

How do I define a general "POJO" ListCellRenderer for a JComboBox


If I have a JComboBox, depending on the platform, the way it renders cells is different. I'm happy with the way that it renders strings. What I would like to achieve is to define a ListCellRenderer that maps from Pojos to Strings, so that I can populate the JComboBox with any objects, but display something other than the contents of the toString method.

My best attempt (which works at runtime, but has warnings at compile time) is as follows

import java.awt.Component;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import javax.swing.ListCellRenderer;

@SuppressWarnings("unchecked") 
public class PojoListRenderer<T> implements ListCellRenderer<Object>
{
    public static interface Extractor<T>
    {
         public String extract(T fromThis);  
    }

    private Extractor<T> myExtractor;
    private ListCellRenderer renderer;

    public PojoListRenderer(Extractor<T> extractor, ListCellRenderer parent)
    {
        myExtractor = extractor;
        renderer = parent;
    }
    public PojoListRenderer(Extractor<T> extractor)
    {
        this(extractor, new DefaultListCellRenderer());
    }

    @Override
    public Component getListCellRendererComponent(JList<?> list,
        Object value, int index, boolean isSelected, boolean cellHasFocus)
    {
        String s = myExtractor.extract((T)value);
        return renderer.getListCellRendererComponent(list, s, index, isSelected, cellHasFocus);
    }
}

which could then be used as follows:

//Assume a class called Notification with methods name() and severity()
JComboBox myNotificationBox = ...;
myNotificationBox.setRenderer
(
     new PojoListRenderer<Notification>
     (
          (notification) -> notification.name() + "/" + notifiation.severity(),
          myNotification.getRenderer()
     )
);

This approach is nice because it means I get all of the highlighting/selection/etc for the default ListCellRenderer of the ComboBox, but I can use the ComboBox as the canonical holder of the domain objects and still have them displayed nicely.

The down side is that the above is clearly not type-safe.

So my questions are:

  1. Is this even a sane way to approach this problem (it seems like it to me)
  2. Have I missed something obvious in the Swing libraries (since this seems like pretty obvious functionality)
  3. Can anyone suggest how to keep the above functionality while also eliminating compiler warnings (and making the above type-safe)

Solution

  • so that I can populate the JComboBox with any objects, but display something other than the contents of the toString method.

    You can check out Combo Box With Custom Renderer. This is my approach to handle POJO's. It does support type safety.

    Probably not exactly what you want but it also solves the problem that your custom renderer has in that is will break the default key selection functionality.