Dalendrion
Dalendrion

Reputation: 69

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?

Upvotes: 1

Views: 3087

Answers (2)

Bon
Bon

Reputation: 3103

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() + "");
    }
}

Upvotes: 3

semTex
semTex

Reputation: 343

If I correctly understand your request, you can use your own javax.swing.ComboBoxEditor.

I just took your example and added a very quick'n'dirty ComboBoxEditor which uses a javax.swing.JTextField and set this as the seconds ComboBox editor.

Maybe this example shows you a way to handle your problem.

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class ComboBoxItem extends JFrame implements ActionListener {

    public ComboBoxItem() {
        final 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);
        this.getContentPane().add(comboBox, BorderLayout.NORTH);

        comboBox = new JComboBox(model);

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

        comboBox.setRenderer(new ItemRenderer());
        comboBox.setEditor(new MyComboBoxEditor()); ///<------- Quick'n'Dirty editor added
        comboBox.addActionListener(this);
        this.getContentPane().add(comboBox, BorderLayout.SOUTH);
    }

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

    class MyComboBoxEditor implements ComboBoxEditor {

        JTextField editor;
        Item       editedItem;

        @Override
        public void addActionListener(final ActionListener l) {

        }

        @Override
        public Component getEditorComponent() {
            if (this.editor == null) {
                this.editor = new JTextField();
            }
            return this.editor;
        }

        @Override
        public Object getItem() {
            return this.editedItem;
        }

        @Override
        public void removeActionListener(final ActionListener l) {
            // TODO Auto-generated method stub

        }

        @Override
        public void selectAll() {
            // TODO Auto-generated method stub

        }

        @Override
        public void setItem(final Object anObject) {
            this.editedItem = (Item) anObject;
            this.editor.setText(String.valueOf(this.editedItem.getId()));
        }

    }

    class ItemRenderer extends BasicComboBoxRenderer {

        @Override
        public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected,
                final boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value != null) {
                final Item item = (Item) value;
                this.setText(item.getDescription().toUpperCase());
            }

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

            return this;
        }
    }

    class Item {

        private final int    id;
        private final String description;

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

        public int getId() {
            return this.id;
        }

        public String getDescription() {
            return this.description;
        }

        @Override
        public String toString() {
            return this.description;
        }
    }

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

You can find the editor between the lines 47 and 88.

Regards

Upvotes: 1

Related Questions