首页 > 解决方案 > JPopupMenu 内的 JCombobox

问题描述

我正在尝试在JCombobox内部使用JPopupMenu,但没有成功,当用户单击标签时,弹出窗口变得可见,

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

这是标签代码,带有鼠标侦听器,它确实显示mousePressedmouseClicked隐藏弹出菜单的事件,在我拥有的菜单内JPanelButtonGroup单击按钮JPanel在面板中心显示不同的,面板和弹出菜单的简短示例代码看起来像这样

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


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

弹出面板包含我上面提到的按钮组,当单击其中一个按钮时,它会显示

    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());

包含的面板JCombobox,问题从这里开始,当我单击组合框以选择颜色时,JPopupMenu被关闭,在另一只手上JCombobox选择什么都不做,我的问题是,我怎样才能强制弹出菜单保持可见,鼠标和弹出侦听器我已经强制它保持可见,但结果我得到IllegalComponentStateException,组件必须显示在屏幕上,我发现类似于我的问题,但它没有提供相关的解决方案,加上此行为在这里作为BUG提交。

将不胜感激任何有用的建议

编辑@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;
            }
        }

    }
}}

标签: javaswingjcomboboxjpopupmenu

解决方案


推荐阅读