Search code examples
javaswingrenderjcombobox

DefaultListCellRenderer does not render empty String correctly when using an editable combo box


I've installed a custom renderer to an editable JCombobox, but I've problems with rendering an empty String. Do you have an idea how to show the empty item with the correct/similar height? Or this is a Java bug?

See the following example and the screenshots for the difference:

expected rendering with a custom renderer

package combo;

import java.awt.Component;
import java.awt.GridLayout;
import java.util.Vector;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.SwingUtilities;

public class MyComboBox {

  private final class CustomCellRenderer extends DefaultListCellRenderer {


    private static final long serialVersionUID = 1L;

    @Override
    public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
      return this;
    }
  }

  private Vector<String> listSomeString = new Vector<String>();
  private JComboBox someComboBox = new JComboBox(listSomeString);
  private JComboBox editableComboBox = new JComboBox(listSomeString);
  private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
  private JFrame frame;

  public MyComboBox() {
    listSomeString.add("");
    listSomeString.add("-");
    listSomeString.add("Snowboarding");
    listSomeString.add("Rowing");
    listSomeString.add("Knitting");
    listSomeString.add("Speed reading");
    someComboBox.setPrototypeDisplayValue("Speed reading");
    someComboBox.setEditable(true);
    editableComboBox.setPrototypeDisplayValue("Speed reading");
    editableComboBox.setEditable(true);
    editableComboBox.setRenderer(new CustomCellRenderer());
    frame = new JFrame();
    frame.setLayout(new GridLayout(0, 1, 10, 10));
    frame.add(someComboBox);
    frame.add(editableComboBox);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocation(100, 100);
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {
        MyComboBox aCTF = new MyComboBox();
      }
    });
  }
}

Solution

  • JComboBox does not use the DefaultListCellRenderer. If you call

    System.out.println(editableComboBox.getRenderer());
    

    you will notice, that a JComboBox uses a BasicComboBoxRenderer instead.

    You just have to change it to

    private final class CustomCellRenderer extends BasicComboBoxRenderer{
      private static final long serialVersionUID = 1L;
    
      @Override
      public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        return this;
      }
    }