Search code examples
javaswinggridbaglayout

GridBagLayout adding extra space to column


I have a JPanel with GridBagLayout as the layout manager and I'm trying to get this arrangement:

https://i.sstatic.net/ZZmVH.png

Ignore the extra dark blue space of the border.

I have in total 5 columns and 3 rows and all the components have setPreferredSize() set to the exact value to fit perfectly in the JPanel which also has a preferred size (170 x 115).

The problem is that GridBagLayout appears to be adding 30 pxls to the last column width, because only adding 30 pxls to the width of the JPanel (200 in total) the components are shown properly, like this:

https://i.sstatic.net/GzjDz.png

but with the last column separated because of the extra space.

It adds 30 pxls because adding 29 pxls to the JPanel's width gives this result:

https://i.sstatic.net/tdmYI.png

which in my experience tells that the space available is too small to show all components and then uses the setMinimumSize().

I don't know where those 30 pxls came from, please can anyone tell me how to make the components fit?

The code is shown below and currently gives this result:

https://i.sstatic.net/p77am.png

Ignore the extra black space of the JFrame.

You can change the width of the JPanel in line 34.

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class Test{
    public static void main (String[] args){
        JFrame f;
        SizeProperties p;

        f = new JFrame();
        p = new SizeProperties();

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setPreferredSize(new Dimension(250,200));
        f.getContentPane().setBackground(Color.BLACK);
        f.setLayout(new FlowLayout());

        f.add(p);
        f.pack();
        f.setVisible(true);
    }
}

final class SizeProperties extends JPanel{
    private GridBagConstraints c;
    private PropertiesLabel xL,yL,wL,hL;
    private PropertiesField xF,yF,wF,hF;
    private ProportionToggleButton ptb;

    SizeProperties(){
        setBackground(new Color(18,101,142));
        setPreferredSize(new Dimension(170,115));//Change width here
        setLayout(new GridBagLayout());

        xL = new PropertiesLabel("x:",25,25);
        xF = new PropertiesField();
        yL = new PropertiesLabel("y:",25,25);
        yF = new PropertiesField();
        wL = new PropertiesLabel("Width:",80,25);
        wF = new PropertiesField();
        hL = new PropertiesLabel("Height:",80,25);
        hF = new PropertiesField();
        ptb = new ProportionToggleButton();

        c = new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(10,10,10,0),0,0);
        add(xL,c);

        c = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(10,0,10,10),0,0);
        add(xF,c);

        c = new GridBagConstraints(2,0,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(10,0,10,0),0,0);
        add(yL,c);

        c = new GridBagConstraints(3,0,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(10,0,10,10),0,0);
        add(yF,c);

        c = new GridBagConstraints(0,1,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,10,10,0),0,0);
        add(wL,c);

        c = new GridBagConstraints(2,1,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,10,10),0,0);
        add(wF,c);

        c = new GridBagConstraints(0,2,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,10,10,0),0,0);
        add(hL,c);

        c = new GridBagConstraints(2,2,2,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,10,10),0,0);
        add(hF,c);

        c = new GridBagConstraints(4,1,1,2,0,0,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,10,10),0,0);
        add(ptb,c);

    }
}

final class PropertiesLabel extends JLabel{
    PropertiesLabel(String label,int w,int h){
        setText(label);
        setPreferredSize(new Dimension(w,h));
        setBackground(Color.BLACK);
        setOpaque(true);
        setForeground(Color.WHITE);
        setFont(new Font("SansSerif",Font.PLAIN,14));
        setHorizontalAlignment(SwingConstants.CENTER);
        setVerticalAlignment(SwingConstants.CENTER);
    }
}

final class PropertiesField extends JTextField{
    private int validNumber = 0;

    PropertiesField(){
        setPreferredSize(new Dimension(45,25));
        setBackground(new Color(202,226,255));
        setForeground(Color.BLACK);
        setFont(new Font("SansSerif",Font.PLAIN,14));
        setHorizontalAlignment(JTextField.CENTER);
        setText("999");
    }
}

final class ProportionToggleButton extends JToggleButton{
    ProportionToggleButton(){
        setPreferredSize(new Dimension(15,60));
    }
}

Thanks in advance.


Solution

  • I have in total 5 columns

    Not from what I can see. You can't just assign a component to a column. You actually need to have 5 components in a single row to create a grid of 5 columns.

    Based on your picture you first row has 4 columns and the last two rows have 3 columns.

    So based on your picture you need to rethink your design. What I see is:

    1. you have three columns based on the last two rows.
    2. now on the first row the x/999 will be a single panel with two components. This panel will be in the 1st column (with the width/height labels).
    3. Also in the first row the y/999 will be a single panel with two components and will start in the 2nd column and have a gridwidth of 2.
    4. The 2nd and 3rd row will contain the 999 component in the second column
    5. the button start in the 2nd row and have a gridheight of 2 and will be contained in the 3rd column

    Also, you should not be setting the preferred size of the components. Each component will determine its own preferred size. The GridBagLayout will then determine the size of each cell based on the components in the row/column.