4

I want to add objects to a JComboBox but show a String on the JComboBox for each object.

For example, in the following html code

<select>
  <option value="1">Item 1</option>
  <option value="2">Item 2</option>
  <option value="3">Item 3</option>
  <option value="4">Item 4</option>
</select>

in the first item, the String that is shown is "Item 1", but the value of the item is "1".

Is there a form to do something like that with a JComboBox?

Adrian
  • 829
  • 5
  • 14
  • 21
  • possible duplicate of [Adding items to a JComboBox](http://stackoverflow.com/questions/17887927/adding-items-to-a-jcombobox) – bummi Jul 28 '15 at 10:33

4 Answers4

5

Start by taking a look at How to Use Combo Boxes, in particular Providing a Custom Renderer

Basically, you want to define your object which will be contained within the combo box...

public class MyObject {
    private String name;
    private int value;

    public MyObject(String name, int value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public int getValue() {
        return value;
    }
}

Then create a custom ListCellRenderer that knows how to renderer it...

public class MyObjectListCellRenderer extends DefaultListCellRenderer {

    public Component getListCellRendererComponent(
                                   JList list,
                                   Object value,
                                   int index,
                                   boolean isSelected,
                                   boolean cellHasFocus) {
        if (value instanceof MyObject) {
            value = ((MyObject)value).getName();
        }
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        return this;
    }
}

Then populate you combo box and apply the cell renderer...

JComboBox box = new JComboBox();
box.addItem(new MyObject(..., ...));
//...
box.setRenderer(new MyObjectListCellRenderer());

You could, equally, override the toString method of your object, but I tend to like to avoid this for display purposes, as I like the toString method to provide diagnostic information about the object, but that's me

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    +1. Besides the good reason given about not overriding `toString` method there's a really simple reason for not doing so: `toString` method can be overridden just once and therefore is a potential bottleneck. This fact is exemplified **[here](http://stackoverflow.com/questions/19094845/item-in-jcombobox-instance-of-an-object/19096485#19096485)**. – dic19 Nov 23 '13 at 00:13
2

If your combo box model contains objects, their toString() method will be used by default to display them in the combo box. If the toString() method displays what you want, you don't have anything to do.

Otherwise, you just need to set a cell renderer to customize the way each object is displayed (and that doesn't limit you to text: you can also change the font, color, icon, etc.).

This is all described in the Swing tutorial.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

For example, in the following html code

For something simple like this, where you have an "ID", "Value" type of data, I do like the approach of a custom Object who's purpose in life is to provide a custom toString() method. See Combo Box With Hidden Data for such an reusable object.

Many people in the forums do recommend a custom renderer. Unfortunately using a custom renderer breaks the default functionality of the comobo box. See Combo Box With Custom Renderer for more information as a solution.

camickr
  • 321,443
  • 19
  • 166
  • 288
0

Yes, that can be done using the object type as the parameter for the JComboBox generic, like this:

public class TestFrame extends JFrame {
    // This will be the JComboBox's item class
    private static class Test {
        private Integer value;
        private String label;

        public Test(Integer value, String label) {
            this.setValue(value);
            this.setLabel(label);
        }

        public Integer getValue() {
            return value;
        }

        public void setValue(Integer value) {
            this.value = value;
        }

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        // The "toString" method will be used by the JComboBox to generate the label for the item
        @Override
        public String toString() {
            return getLabel();
        }        
    }

    public static void main(String[] args) {
        TestFrame frmMain = new TestFrame();
        frmMain.setSize(300, 50);
        frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Here you declare a JComboBox that 
        // uses the type "Test" for item elements 
        JComboBox<Test> cmbCombo = new JComboBox<TestFrame.Test>();

        for (int i = 0; i < 10; i++) {
            // Add some elements for the combo 
            cmbCombo.addItem(new Test(i, String.format("This is the item %d", i + 1)));
        }

        // Listen to changes in the selection
        cmbCombo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JComboBox<Test> cmbCombo = (JComboBox<Test>) e.getSource();

                // The selected element is a "Test" instance, just cast it to the correct type
                Test test = (Test) cmbCombo.getSelectedItem();

                // Manipulate the selected object at will
                System.out.printf("The selected value is '%d'\n", test.getValue());
            }
        });

        frmMain.add(cmbCombo);
        frmMain.setVisible(true);
    }
}
higuaro
  • 15,730
  • 4
  • 36
  • 43