JComboBox与GroupLayout不兼容

3
我在将JComboBox组件放置在GroupLayout中时遇到了一种奇怪的行为。我已将代码简化为下面的最小示例,仅包含一个由GroupLayout布局的JComboBox
观察到的行为如下:
  • 当框架比展开的组合框列表(带有虚拟条目a、b、c)小时,单击组合框上的向下箭头会正确打开它。
  • 当我调整框架大小以大于展开的组合框列表时,展开的组合框列表未打开!
我已经发现以下内容:
  • 当JComboBox的父窗口太小时,javax.swing.PopupFactory会创建一个HEAVY_WEIGHT_POPUP组件。
  • 当父窗口足够大时,将创建LIGHT_WEIGHT_POPUP。
  • 该行为与GroupLayout或其某些副作用明显相关,因为我尝试过的任何其他布局管理器都可以正常工作。
  • 在GroupLayout中使用addGap()时,问题会有所改变,即JComboBox不显示的窗口大小会发生变化。
以下是示例代码 - 欢迎评论:
import java.awt.BorderLayout;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JRootPane;

public class DummyUI_cbdiagnosis extends javax.swing.JPanel {
    private javax.swing.JComboBox cbCategory;

    public DummyUI_cbdiagnosis() {
        initComponents();
    }

    private void initComponents() {
        cbCategory = new JComboBox();
        cbCategory.setModel(new javax.swing.DefaultComboBoxModel(new String[] {
                "a", "b", "c" }));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(
                javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addComponent(cbCategory,
                        javax.swing.GroupLayout.PREFERRED_SIZE,
                        javax.swing.GroupLayout.PREFERRED_SIZE,
                        javax.swing.GroupLayout.PREFERRED_SIZE)));
        layout.setVerticalGroup(layout.createParallelGroup(
                javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addComponent(cbCategory)
        ));
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JRootPane rootPane = frame.getRootPane();
        rootPane.setLayout(new BorderLayout());

        DummyUI_cbdiagnosis panel = new DummyUI_cbdiagnosis();
        rootPane.add(panel, BorderLayout.NORTH);

        frame.pack();
        frame.setVisible(true);
    }
}

如果你导入了包,就不必显式地调用包名了... - Mordechai
1个回答

6
永远不要直接向RootPane添加组件,而应该将它们添加到contentPane中。
frame.add(panel);

或者

frame.setContentPane(panel);

RootPane(根面板)控制以下内容的放置:

  • 菜单栏。
  • 内容。
  • 玻璃板。
  • 最重要的是轻量级弹出窗口(包括JComboBox)、对话框、拖放等。

RootPane使用一个名为RootLayout的特殊布局管理器,不应更改为BorderLayout


你能解释一下为什么我不能添加到根面板吗? - Roman C
不是你的“踩贴者”,但 frame.add() 将内容添加到内容窗格(content pane)中,使得 getContentPane() 变得多余;而 frame.setContentPane() 则替换掉整个内容窗格,这可能是无意之举。更多信息可参考这里 - trashgod
@trashgod 看起来我过时了,旧版本的JDK上JFrame#add(...)会抛出一个Error - Mordechai
谢谢,我没有意识到有 getRootPane() getContentPane() - 我把 getRootPane() 错认为是提供框架顶层面板的方法(不过我还记得在旧版 JDK 中 frame.add() 不起作用的有趣事情)。 - user1830252

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接