How to set the title of a JComboBox when nothing is selected?

helloworld2013 picture helloworld2013 · May 27, 2014 · Viewed 10.1k times · Source

I want to have a JCombobox in my Swing application, which shows the title when nothing is selected. Something like this:

COUNTRY ▼
Spain
Germany
Ireland

I want "COUNTRY" to show when the selected index is -1 and thus, the user wouldn't be able to select it. I tried to put it on the first slot and then overriding the ListCellRenderer so the first element appears greyed out, and handling the events so when trying to select the "title", it selects the first actual element, but I think this is a dirty approach.

Could you lend me a hand?

Answer

DSquare picture DSquare · May 27, 2014

Overriding the ListCellRenderer is a good approach, but you tried something overly complicated. Just display a certain string if you are rendering the cell -1 and there is no selection (value is null). You are not limited to display elements on the list.

The following is an example program that demonstrates it:

enter image description here

enter image description here

Full Code:

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

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;

public class ComboBoxTitleTest
{
    public static final void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run()
            {
                new ComboBoxTitleTest().createAndShowGUI();
            }
        });
    }

    public void createAndShowGUI()
    {
        JFrame frame = new JFrame();

        JPanel mainPanel = new JPanel();
        JPanel buttonsPanel = new JPanel();
        frame.add(mainPanel);
        frame.add(buttonsPanel, BorderLayout.SOUTH);

        String[] options = { "Spain", "Germany", "Ireland", "The kingdom of far far away" };

        final JComboBox comboBox = new JComboBox(options);
        comboBox.setRenderer(new MyComboBoxRenderer("COUNTRY"));
        comboBox.setSelectedIndex(-1); //By default it selects first item, we don't want any selection
        mainPanel.add(comboBox);

        JButton clearSelectionButton = new JButton("Clear selection");
        clearSelectionButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                comboBox.setSelectedIndex(-1);
            }
        });
        buttonsPanel.add(clearSelectionButton);

        frame.pack();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class MyComboBoxRenderer extends JLabel implements ListCellRenderer
    {
        private String _title;

        public MyComboBoxRenderer(String title)
        {
            _title = title;
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean hasFocus)
        {
            if (index == -1 && value == null) setText(_title);
            else setText(value.toString());
            return this;
        }
    }
}

index == -1 in the renderer is the head component that, by default, displays the selected item and where we want to put our title when there's no selection.

The renderer knows that there's nothing selected because the value passed to it is null, which is usually the case. However if for some weird reasons you had selectable null values in your list, you can just let the renderer consult which is the explicit current selected index by passing it a reference to the comboBox, but that is totally unrealistic.