How to use JCombobox inside the JPopupMenu in Swing

246 Views Asked by At

I'm trying to use JCombobox inside the JPopupMenu, but without success, popup becomes visible when user clicks the label,

 label = new JLabel();
 label.addMouseListener(this);

this is the label code, with mouse listener, on mousePressed and mouseClicked events it does display and hide popup menu, inside the menu I have JPanel which contains ButtonGroup, click on buttons displays different JPanel's in the center of the panel, short exmaple of panel and popup menu code looks like this

    popupPanel = new JPanel();
    popupPanel.setLayout(new BorderLayout());


    menu = new JPopupMenu();
    menu.add(BorderLayout.CENTER, popupPanel);
    menu.pack();
    menu.addPopupMenuListener(this);

popup panel contains button groups as i mentioned above, when one of the buttons is clicked it displays

    color_combo_panel = new JPanel();
    color_combo_panel.setLayout(new GridBagLayout());


    color_combo = new JComboBox<>();
    color_combo.addItem(Color.RED.toString());
    color_combo.addItem(Color.BLUE.toString());
    color_combo.addItem(Color.CYAN.toString());
    color_combo.setRenderer(new ColorRenderer());

panel containing JCombobox, problem starts from here, when I click on combo box to select the color, JPopupMenu gets closed, on the ather hand JCombobox selection does nothing, my question is, how can I force popup menu to stay visible, with mouse and popup listeners i have forced it to stay visible, but as a result I get IllegalComponentStateException, component must be shown on the screen, I found problem similar to mine, but it do not provide relevant solution, plus this behavior is submitted as a BUG here.

will much appreciate any useful advice

EDIT minimal reproducible example asked by @camickr

public class PopupTest {

public static void main(String[] args) {

    JFrame frame = new JFrame();
    frame.setSize(new Dimension(500, 500));
    frame.setLayout(new GridBagLayout());
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.add(new ColorCombo());
    frame.setVisible(true);


}


static class ColorCombo extends JComboBox {

    private static final long serialVersionUID = 2L;

    public ColorCombo() {
        setPreferredSize(new Dimension(200, 30));
    }

    @Override
    public void updateUI() {
        ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this);
        if (cui instanceof MetalComboBoxUI) {
            cui = new MetalBrushComboBoxUI();
        } else {
            cui = new BasicBrushComboboxUI();
        }
        setUI(cui);
    }

    class MetalBrushComboBoxUI extends MetalComboBoxUI {
        @Override
        protected ComboPopup createPopup() {
            return new ColorPopup(comboBox);
        }
    }

    class BasicBrushComboboxUI extends BasicComboBoxUI {

        @Override
        protected ComboPopup createPopup() {
            return new ColorPopup(comboBox);
        }
    }


    class ColorPopup extends MouseAdapter implements ComboPopup, ActionListener {

        private JList list = new JList();
        private JComboBox comboBox;
        private JPopupMenu popupMenu;
        private JPanel container, first_color_panel;


        public ColorPopup(JComboBox comboBox) {
            this.comboBox = comboBox;

            container = new JPanel();
            container.setLayout(new BorderLayout());

            JToggleButton first_button = new JToggleButton();
            first_button.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, false));
            first_button.setPreferredSize(new Dimension(20, 20));
            first_button.setBackground(Color.WHITE);
            first_button.addActionListener(this);
            first_button.setActionCommand("color1");


            ButtonGroup buttonGroup = new ButtonGroup();
            buttonGroup.add(first_button);


            JPanel northPanel = new JPanel();
            northPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
            northPanel.add(first_button);

            first_color_panel = new JPanel();
            first_color_panel.setLayout(new GridBagLayout());

            JComboBox<String> color_combo = new JComboBox<>();
            color_combo.setPreferredSize(new Dimension(120, 30));
            for (String color : getColors().keySet())
                color_combo.addItem(color);
            color_combo.setRenderer(new ColorRenderer());
            color_combo.addActionListener(this);
            color_combo.setActionCommand("color1_ground");

            first_color_panel.add(color_combo);

            container.add(northPanel, BorderLayout.NORTH);

            popupMenu = new JPopupMenu();
            popupMenu.add(BorderLayout.CENTER, container);
        }


        @Override
        public void actionPerformed(ActionEvent e) {
            boolean isSet = container.getComponents().length == 2;
            if ("color1".equals(e.getActionCommand())) {
                if (isSet)
                    container.remove(1);
                container.add(first_color_panel, BorderLayout.CENTER);
            }
            container.revalidate();
            popupMenu.repaint();
        }

        @Override
        public void show() {
            this.container.setPreferredSize(new Dimension(this.comboBox.getWidth(), 100));
            popupMenu.add(BorderLayout.CENTER, container);
            popupMenu.pack();
            popupMenu.show(this.comboBox, 0, this.comboBox.getHeight());
        }

        @Override
        public void hide() {
            popupMenu.setVisible(false);
        }

        @Override
        public boolean isVisible() {
            return popupMenu.isVisible();
        }

        @Override
        public JList getList() {
            return list;
        }

        @Override
        public MouseListener getMouseListener() {
            return this;
        }

        @Override
        public MouseMotionListener getMouseMotionListener() {
            return this;
        }

        @Override
        public KeyListener getKeyListener() {
            return null;
        }

        @Override
        public void uninstallingUI() {

        }

        @Override
        public void mouseClicked(MouseEvent e) {
            comboBox.requestFocus();
            toggle();
        }


        private void toggle() {
            if (isVisible()) {
                hide();
            } else {
                show();
            }

        }

        private Map<String, Color> getColors() {
            Map<String, Color> colors = new HashMap<>();
            colors.put("Red", Color.RED);
            colors.put("blue", Color.BLUE);
            colors.put("green", Color.GREEN);
            colors.put("Yellow", Color.YELLOW);
            return colors;
        }

        class ColorRenderer extends JPanel implements ListCellRenderer<String> {


            @Override
            public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, boolean isSelected, boolean cellHasFocus) {
                JPanel panel = new JPanel();
                panel.setLayout(new BorderLayout(3, 3));
                panel.setBorder(BorderFactory.createCompoundBorder(getBorder(),
                        BorderFactory.createEmptyBorder(0, 0, 3, 0)));

                JLabel label = new JLabel();
                label.setOpaque(true);
                label.setPreferredSize(new Dimension(20, label.getHeight()));
                label.setBackground(getColors().get(value));

                JLabel text = new JLabel();
                text.setText(value);

                panel.add(label, BorderLayout.WEST);
                panel.add(text, BorderLayout.CENTER);

                return panel;
            }
        }

    }
}}
0

There are 0 best solutions below