Search code examples
javaswingjcombobox

Editable JComboBox with different text in edit field


I've been looking for a way to have a JComboBox where the items in the list are displayed normally, but in the edit field is showed with just a number.

I came across this code (only slightly modified to my needs):

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class ComboBoxItem extends JFrame implements ActionListener {
    public ComboBoxItem() {
        Vector model = new Vector();
        model.addElement( new Item(1, "car" ) );
        model.addElement( new Item(2, "plane" ) );
        model.addElement( new Item(3, "train" ) );
        model.addElement( new Item(4, "boat" ) );

        JComboBox comboBox;

        comboBox = new JComboBox( model );
        comboBox.addActionListener( this );
        getContentPane().add(comboBox, BorderLayout.NORTH );

        comboBox = new JComboBox( model );

        // I want the comboBox editable.
        //comboBox.setEditable(true);

        comboBox.setRenderer( new ItemRenderer() );
        comboBox.addActionListener( this );
        getContentPane().add(comboBox, BorderLayout.SOUTH );
    }

    public void actionPerformed(ActionEvent e) {
        JComboBox comboBox = (JComboBox)e.getSource();
        Item item = (Item)comboBox.getSelectedItem();
        System.out.println( item.getId() + " : " + item.getDescription() );
    }

    class ItemRenderer extends BasicComboBoxRenderer {
        public Component getListCellRendererComponent(
            JList list, Object value, int index,
            boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index,
                isSelected, cellHasFocus);

            if (value != null) {
                Item item = (Item)value;
                setText( item.getDescription().toUpperCase() );
            }

            if (index == -1) {
                Item item = (Item)value;
                setText( "" + item.getId() );
            }
            return this;
        }
    }

    class Item {
        private int id;
        private String description;

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

        public int getId() {
            return id;
        }

        public String getDescription() {
            return description;
        }

        public String toString() {
            return description;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new ComboBoxItem();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setVisible( true );
     }     
}

This works well, until I make the comboBox editable with comboBox.setEditable(true);.

Background info:

I plan to populate the popup list with object from a database as the user types in the edit field. When the user then selects an item from the popup list, the edit field should display only the object's id, but the popup list should show some more information so the user can make an informed choice.

Can anyone help me make this work whether editable is on or off?


Solution

  • What you need is to override the default editor of the combo box because when you set the combo box to be editable, it uses the editor to render what you selected in the drop down list.

    Below is one way of implementation using BasicComboBoxEditor. You just need to override the setItem method.

    comboBox.setEditor(new ItemEditor());
    
    class ItemEditor extends BasicComboBoxEditor {
        public void setItem(Object anObject) {
            Item item = (Item) anObject;
            editor.setText(item.getId() + "");
        }
    }