javaswinglayout-managergridbaglayout

Getting GridBagLayout Left Justified and JTextBox sized properly


I will admit the GridBagLayout can be a bit of a brainteaser to me.

Testing with various settings gives a variety of results except for the ones I want.

The following code example uses its own GridBagConstraints instance to help ensure each has their own specific settings.

import java.awt.Container;
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 GridLayout2ColumnTest 
{

  public static void main(String[] args) {
    JFrame aWindow = new JFrame();
    aWindow.setBounds(200, 200, 400, 400);
    aWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container content = aWindow.getContentPane();
    content.add(new GridBagLayoutPanel2());
    aWindow.setVisible(true);
  }
}

class GridBagLayoutPanel2 extends JPanel {

  public GridBagLayoutPanel2() {
    GridBagLayout gridbag = new GridBagLayout();
    
    setLayout(gridbag);

    GridBagConstraints gbc1 = new GridBagConstraints();
    gbc1.gridx = 0;
    gbc1.gridy = 0;
    gbc1.anchor = GridBagConstraints.WEST;
    gbc1.fill = GridBagConstraints.BOTH;
    gbc1.insets = new Insets(5, 5, 5, 5);
    JLabel jLabel = new JLabel("Lable 1");
    gridbag.setConstraints(jLabel, gbc1);
    add(jLabel);

    GridBagConstraints gbc2 = new GridBagConstraints();        
    gbc2.gridx = 1;
    gbc2.gridy = 0;
    gbc2.anchor = GridBagConstraints.WEST;
    gbc2.fill = GridBagConstraints.BOTH;
    gbc2.insets = new Insets(5, 5, 5, 5);
    JComboBox jcb = new JComboBox();
    jcb.addItem("This is a long entry for Row 1");
    gridbag.setConstraints(jcb, gbc2);
    add(jcb);

    GridBagConstraints gbc3 = new GridBagConstraints();
    gbc3.gridx = 0;
    gbc3.gridy = 1;
    gbc3.anchor = GridBagConstraints.WEST;
    gbc3.fill = GridBagConstraints.BOTH;
    gbc3.insets = new Insets(5, 5, 5, 5);
    JLabel jLabel2 = new JLabel("Lable 2");
    gridbag.setConstraints(jLabel2, gbc3);
    add(jLabel2);

    GridBagConstraints gbc4 = new GridBagConstraints();        
    gbc4.gridx = 1;
    gbc4.gridy = 1;
    gbc4.anchor = GridBagConstraints.WEST;
    gbc4.fill = GridBagConstraints.BOTH;
    gbc4.insets = new Insets(5, 5, 5, 5);
    JTextField jtf = new JTextField(5);
    gridbag.setConstraints(jtf, gbc4);
    add(jtf);
    
  }
}

The above code generates the following.

enter image description here

What I would like is the following results.

enter image description here

I did read that setPreferredSize and setMinimumSize should not be used.

So, what is the secret to getting the desired results and any good tips to keep in mind when working with this layout?


Solution

  • Oh, runnable code 😊

    The basic answer to you question is to make use of the weightx property. Basically, you want to allocate all the remaining horizontal space to the combo box and text field

    I'd also get rid of the fill property, as it won't generate the results you're after.

    enter image description here

    class GridBagLayoutPanel2 extends JPanel {
    
        public GridBagLayoutPanel2() {
            GridBagLayout gridbag = new GridBagLayout();
    
            setLayout(gridbag);
    
            GridBagConstraints gbc1 = new GridBagConstraints();
            gbc1.gridx = 0;
            gbc1.gridy = 0;
            gbc1.anchor = GridBagConstraints.WEST;
            //gbc1.fill = GridBagConstraints.BOTH;
            gbc1.insets = new Insets(5, 5, 5, 5);
            JLabel jLabel = new JLabel("Lable 1");
            gridbag.setConstraints(jLabel, gbc1);
            add(jLabel);
    
            GridBagConstraints gbc2 = new GridBagConstraints();
            gbc2.gridx = 1;
            gbc2.gridy = 0;
            gbc2.anchor = GridBagConstraints.WEST;
            //gbc2.fill = GridBagConstraints.BOTH;
            gbc2.insets = new Insets(5, 5, 5, 5);
            
            gbc2.weightx = 1;
            
            JComboBox jcb = new JComboBox();
            jcb.addItem("This is a long entry for Row 1");
            gridbag.setConstraints(jcb, gbc2);
            add(jcb);
    
            GridBagConstraints gbc3 = new GridBagConstraints();
            gbc3.gridx = 0;
            gbc3.gridy = 1;
            gbc3.anchor = GridBagConstraints.WEST;
            //gbc3.fill = GridBagConstraints.BOTH;
            gbc3.insets = new Insets(5, 5, 5, 5);
            JLabel jLabel2 = new JLabel("Lable 2");
            gridbag.setConstraints(jLabel2, gbc3);
            add(jLabel2);
    
            GridBagConstraints gbc4 = new GridBagConstraints();
            gbc4.gridx = 1;
            gbc4.gridy = 1;
            gbc4.anchor = GridBagConstraints.WEST;
            //gbc4.fill = GridBagConstraints.BOTH;
            gbc4.insets = new Insets(5, 5, 5, 5);
            gbc4.weightx = 1;
            JTextField jtf = new JTextField(5);
            gridbag.setConstraints(jtf, gbc4);
            add(jtf);
    
        }
    }
    

    As a minor note, you should also make use of the "line" anchors instead of the compass ones. This makes it easier to adopt the UI to RTL languages (I know, how likely are you to do that 😝)

    In this case, it's as simple as changing GridBagConstraints.WEST to GridBagConstraints.LINE_START