Search code examples
javaswinglayout-managergridbaglayout

JPanel in GridBagLayout does not keep proportion (weightx)


I have the following situation. I've created a JPanel with GridBagLayout with the following proportions. I want to get this straight, and after that I will add more components. For now I have something like

------------------------------------
|LABEL 45%  | LABEL 10% | LABEL 45%|
------------------------------------

Each label takes 1 cell horizontally and vertically (gridwidth/height = 1)

Weights (x) are 0.45, 0.1 and 0.45 (from left to right)

Weights (y) are 0.0

All labels have fill GBC.HORIZONTAL and the anchors are WEST, WEST, EAST.

JPanel topPanel = new JPanel(new GridBagLayout());

    topPanel.add(new JLabel("1"), new GridBagConstraints(
        0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));
    topPanel.add(new JLabel("2"), new GridBagConstraints(
        1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.BOTH, INSETS_0PX, 0, 0));
    topPanel.add(new JLabel("3"), new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));

At this point everything is OK, the first label gets the exact same space as the right label (which is 45% of the width available, and the other one gets 10%). Perfect.

But when I try to add, instead of a label (either left/right), another JPanel with a GridBagLayout, the proportions are not kept as defined.

In the left I want to add a JPanel which is defined as follows

----------------------
|JLabel..............|
|--------------------|
|JTextArea...........|
|....................|
----------------------

JLabel has weights 0.0 (for both x/y), WEST anchor, and fill NONE

JTextArea - weights 1.0(x), 1.0, WEST anchor, fill BOTH (in order to stretch)

myPanel = new JPanel(new GridBagLayout());
myPanel.add(new JLabel("TITLE", new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
myPanel.add(new JTextArea(5,25), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
        GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));

In the right, I want to add a JPanel with a GridBagLayout which holds two other JPanels with GridBagLaouts (there's no point in describing now how is defined).

--> therefore, at the moment when I add the left panel instead of the label, it gets somewhere around 60% of the screen (which is not right, it should get 45%).

Can you spot what is wrong? I'm out of ideas

LE: here's the simple example

public class Example extends JFrame {

public Example() {
    init();
}

private JPanel createPanel(Component comp) {
    JPanel topPanel = new JPanel(new GridBagLayout());

    topPanel.add(comp, new GridBagConstraints(
        0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
    topPanel.add(new JLabel("2"), new GridBagConstraints(
        1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.BOTH, new Insets(0,0,0,0), 0, 0));
    topPanel.add(new JLabel("3"), new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));

    return topPanel;
}

private JPanel getPanelWithLabel() {
    return createPanel(new JLabel("1"));
}

private JPanel getPanelWithPanel() {
    JPanel myPanel = new JPanel(new GridBagLayout());
    myPanel.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
    myPanel.add(new JTextArea(5,25), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
            GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0, 0));
    return createPanel(myPanel);
}

private void init() {
    setTitle("Simple example");
    setSize(800, 200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    JPanel panel = new JPanel(new BorderLayout());
    panel.add(getPanelWithLabel(), BorderLayout.CENTER);
//panel.add(getPanelWithPanel(), BorderLayout.CENTER);

    add(panel);
    setVisible(true);
}

public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            Example ex = new Example();
        }
    });

}
}

Solution

  • The problem lays with the rows of your JTextArea.

    As 25 rows is wider than the 45%, it expends itself.

    Instead of using 25, I'd use the WIDTH of the container (myPanel)


    Solution

    myPanel.add(new JTextArea(5,myPanel.WIDTH), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
                    GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));
    

    Output

    enter image description here


    EDIT

    Since the sizes are still different with this method. I tried to create first a JPanel and to add the JLabel to it.


    Solution

    JPanel threeCont = new JPanel(new GridBagLayout());
    threeCont.add(new JLabel("3"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
    // We add myPanel and two(JLabel) to topPanel first and than the below.
    topPanel.add(threeCont, new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));
    

    Output

    System.out.println("First Panel's Size : " + myPanel.getSize());
    System.out.println("Second Panel's Size : " +two.getSize());
    System.out.println("Third Panel's Size : " +threeCont.getSize());
    

    Console

    First Panel's Size : java.awt.Dimension[width=441,height=96]
    Second Panel's Size : java.awt.Dimension[width=98,height=96]
    Third Panel's Size : java.awt.Dimension[width=441,height=16]
    

    Full code

    public static void main(String[]a) {
        JFrame fr = new JFrame();
        fr.setSize(new Dimension(1000,1000));
        fr.setLocationRelativeTo(null);
        JPanel topPanel = new JPanel(new GridBagLayout());
        Insets INSETS_0PX = new Insets(0,0,0,0);
        JLabel one = new JLabel("1");
        JLabel two = new JLabel("2");
        one.setBackground(Color.yellow);
        two.setBackground(Color.blue);
    
        JPanel myPanel = new JPanel(new GridBagLayout());
        myPanel.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
        myPanel.add(new JTextArea(5,myPanel.WIDTH), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));
    
        JPanel threeCont = new JPanel(new GridBagLayout());
        threeCont.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
    
        topPanel.add(myPanel, new GridBagConstraints(
            0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
            GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));
    
        topPanel.add(two, new GridBagConstraints(
            1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
            GridBagConstraints.BOTH, INSETS_0PX, 0, 0));
    
        topPanel.add(threeCont, new GridBagConstraints(
            2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
            GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));
    
    
        fr.add(topPanel);
    
        fr.setVisible(true);
    
        System.out.println("First Panel's Size : " + myPanel.getSize());
        System.out.println("Second Panel's Size : " +two.getSize());
        System.out.println("Third Panel's Size : " +threeCont.getSize());
    }