Bitcoin

Bitcoin
Bitcoin

Custom GUI JComboBox

This tutorial helps you building a JComboBox component in Java Swing with custom GUI renderer, rather than its default look and feel. Sometimes, it would be desirable to have a dropdown list like the following pictures:
custom combobox gui 1
or:
custom combobox gui 2
Looks very nice, right? Let’s see how we can build such components in Java Swing. Assuming we want to create a dropdown list that allows users to select a country, as shown in the first screenshot.

1. How to create custom GUI for JCombobox

Generally, it is possible to provide a custom GUI implementation for Swing-based components by providing renderers and editors. For example:

1
2
3
JComboBox comboBox = new JComboBox();
comboBox.setRenderer(new MyComboBoxRenderer());
comboBox.setEditor(new MyComboBoxEditor());
The renderer class must implement javax.swing.ListCellRenderer interface. It is used to render component’s GUI in normal state. For example, the following class, MyComboBoxRenderer – implements a simple renderer which is a JLabel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.sjavaspot.swing.combobox
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
public class MyComboBoxRenderer extends JLabel implements ListCellRenderer {
    public MyComboBoxRenderer() {
        setOpaque(true);
        setFont(new Font("Arial", Font.BOLD | Font.ITALIC, 14));
        setBackground(Color.BLUE);
        setForeground(Color.YELLOW);
    }
     
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        setText(value.toString());
        return this;
    }
}
As we can see, the renderer class has to override the method getListCellRendererComponent() which is defined by the interface ListCellRenderer. The method must return a subclass of Component class which is rendered as list item in the combo box. In the example above, it returns an instance of JLabel class, and results in a combo box looks like following:
custom combobox gui 3

On the other hand, the editor class must implement ComboBoxEditor interface or extends one of ComboBoxEditor’s implementing classes, such as BasicComboBoxEditor. It is used to render component’s GUI in edit state. For example, the following class, MyComboBoxEditor – implements a simple editor which is a JPanel containing a JLabel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.sjavaspot.swing.combobox
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicComboBoxEditor;
public class MyComboBoxEditor extends BasicComboBoxEditor {
    private JLabel label = new JLabel();
    private JPanel panel = new JPanel();
    private Object selectedItem;
     
    public MyComboBoxEditor() {
         
        label.setOpaque(false);
        label.setFont(new Font("Arial", Font.BOLD, 14));
        label.setForeground(Color.BLACK);
         
        panel.setLayout(new FlowLayout(FlowLayout.LEFT, 52));
        panel.add(label);
        panel.setBackground(Color.GREEN);
    }
     
    public Component getEditorComponent() {
        return this.panel;
    }
     
    public Object getItem() {
        return "[" this.selectedItem.toString() + "]";
    }
     
    public void setItem(Object item) {
        this.selectedItem = item;
        label.setText(item.toString());
    }
     
}
This editor class extends the BasicComboBoxEditor class and overrides the following three methods:
    • Component getEditorComponent(): returns a subclass object of Component class which is used to render the component in edit state. In the example above, the editor is a JPanel.
    • setItem(Object): this method is called whenever an item is selected in the dropdown list. It is for the editor has to render the component based on the item passed. In the example above, it shows a label with green background and bold font.
    • Object getItem(): returns the selected item in the dropdown list. This method is called by the JComboBox’s getSelectedItem() method.
This editor makes the combo box looks something like the following:
custom combobox editor
So far we understand the nuts and bolts of the renderer and editor for a JComboBox. Let’s see how the following nice-looking country combo box is implemented in the next sections:
country combo box
NOTE: the combo box must be editable in order to use custom renderer and editor:

1
comboBox.setEditable(true);

2. Code renderer class for JComboBox

Code of the renderer class is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.sjavaspot.swing.combobox
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
/**
 * Customer renderer for JComboBox
 * @author www.sjavaspot.com
 *
 */
public class CountryItemRenderer extends JPanel implements ListCellRenderer {
    private JLabel labelItem = new JLabel();
     
    public CountryItemRenderer() {
        setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weightx = 1.0;
        constraints.insets = new Insets(2222);
         
        labelItem.setOpaque(true);
        labelItem.setHorizontalAlignment(JLabel.LEFT);
         
        add(labelItem, constraints);
        setBackground(Color.LIGHT_GRAY);
    }
     
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        String[] countryItem = (String[]) value;
        // set country name
        labelItem.setText(countryItem[0]);
         
        // set country flag
        labelItem.setIcon(new ImageIcon(countryItem[1]));
         
        if (isSelected) {
            labelItem.setBackground(Color.BLUE);
            labelItem.setForeground(Color.YELLOW);
        else {
            labelItem.setForeground(Color.BLACK);
            labelItem.setBackground(Color.LIGHT_GRAY);
        }
         
        return this;
    }
}
As we can see, a JLabel is used for displaying an icon of country flag and country name. Its background and foreground are set differently for selected state and non-selected state.

3. Code editor class for JComboBox

The editor class is implemented as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.sjavaspot.swing.combobox
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicComboBoxEditor;
/**
 * Editor for JComboBox
 * @author wwww.sjavaspot.com
 *
 */
public class CountryItemEditor extends BasicComboBoxEditor {
    private JPanel panel = new JPanel();
    private JLabel labelItem = new JLabel();
    private String selectedValue;
     
    public CountryItemEditor() {
        panel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weightx = 1.0;
        constraints.insets = new Insets(2522);
         
        labelItem.setOpaque(false);
        labelItem.setHorizontalAlignment(JLabel.LEFT);
        labelItem.setForeground(Color.WHITE);
         
        panel.add(labelItem, constraints);
        panel.setBackground(Color.BLUE);       
    }
     
    public Component getEditorComponent() {
        return this.panel;
    }
     
    public Object getItem() {
        return this.selectedValue;
    }
     
    public void setItem(Object item) {
        if (item == null) {
            return;
        }
        String[] countryItem = (String[]) item;
        selectedValue = countryItem[0];
        labelItem.setText(selectedValue);
        labelItem.setIcon(new ImageIcon(countryItem[1]));      
    }  
}
The editor also uses a JLabel to display the selected country item but with different background and foreground than the renderer. It returns country name as the selected object from getItem() method.

4. Code custom combo box class

We implement a custom class that extends from JComboBox as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.sjavaspot.swing.combobox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
/**
 * A custom combo box with its own renderer and editor.
 * @author wwww.sjavaspot.com
 *
 */
public class CountryComboBox extends JComboBox {
    private DefaultComboBoxModel model;
     
    public CountryComboBox() {
        model = new DefaultComboBoxModel();
        setModel(model);
        setRenderer(new CountryItemRenderer());
        setEditor(new CountryItemEditor());
    }
     
    /**
     * Add an array items to this combo box.
     * Each item is an array of two String elements:
     * - first element is country name.
     * - second element is path of an image file for country flag.
     * @param items
     */
    public void addItems(String[][] items) {
        for (String[] anItem : items) {
            model.addElement(anItem);
        }
    }
}
This combo box uses the renderer class and editor class shown above. In addition, it uses a DefaultComboBoxModel to hold items. The addItems(String[][]) method is for adding an array of items to the drop down list. Each item is also an array in which the first item is country name and the second is path of an image file represents country flag.  You can get the complete code here

No comments:

Post a Comment

Facebook