This discussion is archived
2 Replies Latest reply: Jan 31, 2012 4:42 PM by Jörg RSS

Extended JComboBox

Jörg Explorer
Currently Being Moderated
Hello,

I just finished the following class, but I'm not capable of avoiding two warnings (except supressing them).
Would somebody kindly have a look at the green comments? I can provide test code if required, too.
import java.awt.*; 
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;

public class DifferentPopupCombo extends JComboBox<DifferentPopupCombo.Item> {
  public static final long serialVersionUID= 80L;
  protected int popupWidth;

//  @SuppressWarnings("unchecked")
  public DifferentPopupCombo(Item[] items) {
    super(items);
    setUI(new DifferentPopupComboUI());
    setRenderer(new PopupRenderer()); // unchecked conversion here
  }


  public Dimension getPopupSize() {
    Dimension size = getSize();
    if (popupWidth < 1) popupWidth = size.width;
    return new Dimension(popupWidth, size.height);
  }


  public void setPopupWidth(int width) {
    popupWidth = width;
  }


  static class Item {
    private String id;
    private String resultView;

    public Item(String id, String resultView) {
      this.id = id;
      this.resultView = resultView;
    }

    public String getId() {
      return id;
    }

    public String getResultView() {
      return resultView;
    }

    public String toString() {
      return resultView;
    }
  }


  class PopupRenderer extends BasicComboBoxRenderer {
    public static final long serialVersionUID= 81L;

//    @SuppressWarnings("rawtypes")
//found raw type: JList
    public Component getListCellRendererComponent(JList list, Object value,
               int index, boolean isSelected, boolean cellHasFocus) {
      super.getListCellRendererComponent(list, value, index, isSelected,
                          cellHasFocus);
      if (index>-1) setText( ((Item)value).getId() );
      return this;
    }
  }


  class DifferentPopupComboUI extends MetalComboBoxUI {

    protected ComboPopup createPopup() {
      BasicComboPopup popup = new BasicComboPopup(comboBox) {
     public static final long serialVersionUID= 82L;
     public void show() {
       Dimension popupSize= getPopupSize();
       popupSize.setSize(popupSize.width, getPopupHeightForRowCount
                         (comboBox.getMaximumRowCount()));
       Rectangle popupBounds = computePopupBounds(0,
           comboBox.getBounds().height,popupSize.width, popupSize.height);
       scroller.setMaximumSize(popupBounds.getSize());
       scroller.setPreferredSize(popupBounds.getSize());
       scroller.setMinimumSize(popupBounds.getSize());
       list.invalidate();
       int selectedIndex = comboBox.getSelectedIndex();
       if (selectedIndex == -1)
         list.clearSelection();
       else
         list.setSelectedIndex(selectedIndex);            
       list.ensureIndexIsVisible(list.getSelectedIndex());
       setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
       show(comboBox, popupBounds.x, popupBounds.y);
     }
      };
      popup.getAccessibleContext().setAccessibleParent(comboBox);
      return popup;
    }
  }

}
  • 1. Re: Extended JComboBox
    DrClap Expert
    Currently Being Moderated
    As for the second instance: if you look at the API documentation for the ListCellRenderer (Java 7 version) you'll see in the code there the technique for not using a raw type in that position.

    As for the first instance: I'm surprised that BasicComboBoxRenderer isn't generified, even though it implements ListCellRenderer<E>. If you want to get rid of the warning then I think your only option is to write your own implementation of ListCellRenderer<DifferentPopupCombo.Item> -- although you could try declaring that your PopupRenderer implements ListCellRenderer<DifferentPopupCombo.Item> and see if you can get rid of the resulting compiler errors.
  • 2. Re: Extended JComboBox
    Jörg Explorer
    Currently Being Moderated
    Thank you for looking at the code.

    I had seen the example in the API, but had adopted only the "JList<?>", which
    made things worse. Now I did everything as in the example and extended JLabel
    instead of BasicComboBoxRenderer, which is good against the warnings: both of
    them disappeared.
      class PopupRenderer extends JLabel implements ListCellRenderer<Object> {
        public static final long serialVersionUID= 81L;
    
        public Component getListCellRendererComponent(JList<?> list, Object value,
                   int index, boolean isSelected, boolean cellHasFocus) {
          System.out.println(index+" "+value);
          if (index>-1) setText( ((Item)value).getId() );
          return this;
        }
      }
    Only the class has lost now its functionality, which is to display a value
    in the combo field different from the popup selection and to return the
    correct index in actionPerformed(). Extending JLabel obviously renders the
    popup list as well as the combo field.
    I add the test code, just in case.
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class DifferentPopupCmbTest extends JFrame {
      
      public DifferentPopupCmbTest() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(250,200);
        Container cp= getContentPane();
        cp.setLayout(new FlowLayout(FlowLayout.CENTER, 60, 50));
    
        final DifferentPopupCombo cmb= new DifferentPopupCombo(
          new DifferentPopupCombo.Item[] {
         new DifferentPopupCombo.Item("France","EUR"),
         new DifferentPopupCombo.Item("Germany","EUR"),
         new DifferentPopupCombo.Item("UK","GBP"),
         new DifferentPopupCombo.Item("USA","US$")
          }
        );
        cmb.setPopupWidth(70);
        cmb.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
         System.out.println("Index: "+cmb.getSelectedIndex()); 
          }
        });
        cp.add(cmb);
        setVisible(true);
      }
    
    
      public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
          public void run() {
         new DifferentPopupCmbTest();
          }
        });
      }
    
    }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points