Search code examples
javaswingbackground-imagejcombobox

How to add background image to JComboBox?


I asked here how to add background image to JComboBox properly, but didn't see answers, so i thought that i should separate these two questions...

So. How to add background image to JComboBox text field and to JComboBox popup panel properly?

UPD: Some code for you)

Current code:

// ... Renderer

public class CBoxListCellRenderer implements ListCellRenderer {

     ImagePanel panel;
     JLabel label = new JLabel();

     public CBoxListCellRenderer(Image img) {panel = new ImagePanel(img);}

     public void setImage(Image img) {panel.setImage(img);}

     @Override
     public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
          label.setText(value.toString());
          panel.add(label);
          return panel;
     }
}

// ... ImagePanel

public class ImagePanel extends JPanel {

    private BufferedImage img;

    public ImagePanel(String img) {
        setImage(img);
    }

    public void setImage(String img)
    {
        try {
            this.img = ImageIO.read(this.getClass().getResource(img));
        } catch (IOException ex) {
           ex.printStackTrace();
        }
        Dimension size = new Dimension(this.img.getWidth(), this.img.getHeight());
        setSize(size);
    }

    @Override
    public void paintComponent(Graphics g) {
        g.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, img.getWidth(), img.getHeight(), this);
    }
}

// ... Colorizing arrow

class ColorArrowUI extends BasicComboBoxUI {

     public static ComboBoxUI createUI(JComponent c) {
         return new ColorArrowUI();
     }

     @Override protected JButton createArrowButton() {
          return new BasicArrowButton(
               BasicArrowButton.SOUTH,
               Color.cyan, Color.magenta,
               Color.yellow, Color.blue);
     }
}

// ... Creating object

combo_language = new JComboBox(new DefaultComboBoxModel(new String[] { "English", "日本語", "Русский" }));
combo_language.setBorder(null);
combo_language.setRenderer(new CBoxListCellRenderer(new ImageIcon(getClass().getResource("/Images/form.png")).getImage()));
combo_language.setUI(new ColorArrowUI());


// ... Putting JComboBox to JFrame

Solution

  • Here's an example of a custom ListCellRenderer. I return a JPanel that has painted an image to it then added a JLabel that holds the value of the list object. There's room for improvement on it, but it's just an example of what you can do.

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class TestCBoxListCellRenderer {
    
        public TestCBoxListCellRenderer() {
            String[] list = {"Hello World 1", "Hello World 2", "Hello World 3"};
            JComboBox box = new JComboBox(list);
            box.setRenderer(new CBoxListCellRenderer());
    
            JOptionPane.showMessageDialog(null, box, "Check out this Renderer", JOptionPane.PLAIN_MESSAGE);
        }
    
        public static void main(String[] args) {
            new TestCBoxListCellRenderer();
        }
    
        class BackGroundPanel extends JPanel {
    
            BufferedImage img = null;
    
            public BackGroundPanel() {
                try {
                    img = ImageIO.read(TestCBoxListCellRenderer.class.getResource("/res/leafcell.png"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(img, 0, 0, getWidth(), getHeight(),
                        0, 0, img.getWidth(), img.getHeight(), this);
            }
        }
    
        private class CBoxListCellRenderer implements ListCellRenderer {
    
            final BackGroundPanel panel = new BackGroundPanel();
            JLabel label = new JLabel();
    
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    
                label.setText(value.toString());
                panel.add(label);
    
                return panel;
            }
        }
    }
    

    enter image description here

    You may want to add a thin line border or do something when its selected, its up to you. Use the variables from the getListCellRendererComponent method to render to your liking accordingly