Search code examples
javaswinggridwidthgridbaglayout

GridBagLayout: Last component affects grid width


i'm facing a problem with Javas GridBagLayout.

Running the following code:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class Main extends JFrame{

    public static void main (String [] args){
        new Main(); 
    }

    public Main(){
        add(getPanel());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        setSize(600, 150);
    }

    private JPanel getPanel(){
        JPanel panel = new JPanel(new GridBagLayout());

        JLabel label1 = new JLabel("Label 1");
        JLabel label2 = new JLabel("Label 2");
        JLabel label3 = new JLabel("Label 3");

        JTextField area1 = new JTextField();
        JTextField area2 = new JTextField();

        JComboBox<String> box = new JComboBox<String>();
        box.addItem("One One One");
        box.addItem("Two Two Two");

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(10, 10, 10, 10);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0;
        panel.add(label1, gbc);

        gbc.gridx = 1;
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(area1, gbc);

        gbc.gridx = 2;
        gbc.weightx = 0;
        gbc.fill = GridBagConstraints.NONE;
        panel.add(label2, gbc);

        gbc.gridx = 3;
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel.add(area2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.weightx = 0;
        panel.add(label3, gbc);

        gbc.weightx = 1;
        gbc.gridx = 1;
        panel.add(box, gbc);

        return panel;
    }
}

Produces the following window:

Problem with GridBagLayout Screenshot

But the two JTextFields should be in the same width.

If I don't add the JComboBox everything is fine:

enter image description here

My question is: why does the last component affect the grid width of the prior components? The really strange thing for me is that the right JTextField gets smaller, if the JComboBox length increases. Actually it looks like the length of the left JTextField equals the length of the right JTextField + the length of the JComboBox. What is the trick to have two in length equally textfields and a JComboBox in the next row?

Thanks in advance!


Solution

  • According to the GridBagLayout informations :

    Essentially, GridBagLayout places components in rectangles (cells) in a grid, and then uses the components' preferred sizes to determine how big the cells should be.

    Since when you add the JComboBox, it's preferred size is larger than your JTextFields, the grids at x=1 will take a larger proportion of the place in the JPanel because the weightx that are equals will share the place they need according to their preferred size..

    That's why adding the JComboBox "pushes" the gridx=2. To avoid that, you can decide on a number of columns for the JTextField when you create them :

    JTextField area1 = new JTextField(15);
    JTextField area2 = new JTextField(15);
    

    or add place holder text so the preferred size of the JTextFields is higher than 0. If you were to do

    box.setPreferredSize(area1.getPreferredSize());
    panel.add(box, gbc);
    

    you would notice the JComboBox being almost invisible as the preferred size is small and that would, on the other hand, make your panel equal on each side.

    I would also recommend that you use a new GridBagConstraints for each component to avoid copying over the values of the component added before that you don't reset a value to.