Alberto acepsut
Alberto acepsut

Reputation: 2022

Java Swing: how to render a combobox with different line style?

I would like to have a ComboBox displaying some different line styles, such as solid, dotted, dashed etc.

How to create a custom render to accomplish this?

Thanks all.

Upvotes: 2

Views: 3314

Answers (2)

Guillaume Polet
Guillaume Polet

Reputation: 47608

The good way to do this is to use a CustomRenderer. You can either use predefined images or paint the line stroke on the fly. Here is an example of the latter option:

import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.UnsupportedLookAndFeelException;

public class TestComboBox {

    private static enum LineType {

        PLAIN {
            @Override
            public Stroke getStroke() {
                return new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 1.0f, new float[] { 1.0f }, 1);
            }
        },
        DOTTED {
            @Override
            public Stroke getStroke() {
                return new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 1.0f, new float[] { 0.1f, 5.0f }, 1);
            }

        },
        DASHED {
            @Override
            public Stroke getStroke() {
                return new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 1.0f, new float[] { 3.0f, 3.0f }, 1);
            }

        };
        public abstract Stroke getStroke();
    }

    public class LineRenderer extends JPanel implements ListCellRenderer {
        private LineType value;

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (value instanceof LineType) {
                setLineType((LineType) value);
            } else {
                setLineType(null);
            }
            return this;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            if (value != null) {
                g2d.setStroke(value.getStroke());
                g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
            }

        }

        private void setLineType(LineType value) {
            this.value = value;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 20);
        }

    }

    protected void initUI() {
        final JFrame frame = new JFrame(TestComboBox.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel(new GridBagLayout());
        final JComboBox comboBox = new JComboBox(LineType.values());
        comboBox.setRenderer(new LineRenderer());
        comboBox.setSelectedItem(null);
        comboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        JOptionPane.showMessageDialog(comboBox, "You have selected " + comboBox.getSelectedItem());
                    }
                });
            }
        });
        panel.add(comboBox);
        frame.add(panel);
        frame.setSize(300, 100);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestComboBox().initUI();
            }
        });
    }
}

Upvotes: 6

davidXYZ
davidXYZ

Reputation: 729

Take a look at this answer that I gave for a custom JComboBox editor. In that solution, I extended the BasicComboBoxEditor class, modified the editing component and used a new instance of that in setEditor().

Similarly, you can extend BasicComboBoxRenderer, modify the borders of the rendering component as you wish, then use setRenderer() to set a new instance of it to your JComboBox.

Upvotes: 1

Related Questions