JComboBox does not play well with GroupLayout

java, jcombobox, swing

Solution

Never ever add components to the `RootPane` itself, rather add them to the `contentPane`.

frame.add(panel);

or

frame.setContentPane(panel);

A `RootPane` has control of where to put the:

- Menu bar.

- Content.

- Glass pane.

- And most important, lightweight popups (inc. `JComboBox`), dialogs, drag and drops, etc.

`RootPane` uses a special layout manager called `RootLayout`, and shouldn't be changed to `BorderLayout`.

Problem

I ran into a strange kind of behavior when putting `JComboBox` components inside a `GroupLayout`. I've reduced the code to the below minimal example, featuring exactly one `JComboBox` layed out by `GroupLayout`. The observed behavior is as follows: - When the frame is smaller than the expanded combo box list (with dummy entries a, b, c), clicking on the little down arrow on the combo box opens it correctly. - When I resize the frame to be bigger than the expanded combo box list would be, the expanded combo box list is not opened! What I've found out already: - When the parent window of a JComboBox is too small, javax.swing.PopupFactory creates a HEAVY_WEIGHT_POPUP component. - When the parent window is big enough, a LIGHT_WEIGHT_POPUP is being created. - The behavior is definitely related to GroupLayout or some side effects of it, since any other layout managers I tried work just fine. - When using addGap() in GroupLayout the problem changes a bit, i.e. the window sizes where the JComboBox does not show up change. This is the sample code - comments are welcome: ``` 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); } } ```

Original source