java - JPopupMenu 内的 JCombobox
问题描述
我正在尝试在JCombobox
内部使用JPopupMenu
,但没有成功,当用户单击标签时,弹出窗口变得可见,
label = new JLabel();
label.addMouseListener(this);
这是标签代码,带有鼠标侦听器,它确实显示mousePressed
和mouseClicked
隐藏弹出菜单的事件,在我拥有的菜单内JPanel
,ButtonGroup
单击按钮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;
}
}
}
}}
解决方案
推荐阅读
- php - 将字符串的一部分放入变量中
- javascript - Vue/JS:在不同的类方法中访问相同的变量
- javascript - 如何在 JavaScript 中的数组中获取对象?
- gsuite-addons - 从 Chrome 商店迁移到 g Suite 市场
- tensorflow - google colab 上已安装驱动器的数据加载器
- python - 有没有办法让pygame检测我的光标在什么颜色上
- c - 如何从字符串文字中打印特殊字符作为它们的“反斜杠”符号?
- github - 如何查看未加密的 git 机密?
- php - 如何在单个 tables.sql 文件中编写多个查询并使用 PHP 上传?
- reactjs - 如何定位 iframe 中的 reCAPTCHA 元素以显示它,而不是其他(Gatsby/React)?