Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java GridBagLayout not working

I'm trying to use GridBagLayout, but I don't get what I expect and I can't find the error in this code:

public class GridBagEx1 extends JPanel {

    private static final long serialVersionUID = 1L;

    protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c) {
        JButton button = new JButton(name);
        gridbag.setConstraints(button, c);
        add(button);
    }

    public void init() {
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        setLayout(gridbag);

        c.fill = BOTH;

        c.weightx = 1.0;
        c.weighty = 1.0;

        c.anchor = CENTER;

        c.insets.top = 5;
        c.insets.bottom = 5;
        c.insets.left = 5;
        c.insets.right = 5;

        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button1", gridbag, c);      

        c.gridx = 2;
        c.gridy = 0;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button2", gridbag, c);

        c.gridx = 3;
        c.gridy = 0;
        c.gridheight = 2;
        c.gridwidth = 2;
        makebutton("Button3", gridbag, c);

        c.gridx = 0;
        c.gridy = 1;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button4", gridbag, c);

        c.gridx = 1;
        c.gridy = 1;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button5", gridbag, c);

        c.gridx = 0;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button6", gridbag, c);

        c.gridx = 1;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 2;
        makebutton("Button7", gridbag, c);

        c.gridx = 3;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button8", gridbag, c);

        c.gridx = 4;
        c.gridy = 2;
        c.gridheight = 1;
        c.gridwidth = 1;
        makebutton("Button9", gridbag, c);
    }

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        GridBagEx1 ex1 = new GridBagEx1();

        ex1.init();

        frame.add(ex1);
        frame.pack();
        frame.setVisible(true);
    }
}

This picture illustrate what I need:

Programmers love paint

Yellow are button name, red are row and columns.

This is what really happens: Whats wrong here?

Can anyone explain what is wrong in my code?

like image 296
Emax Avatar asked Sep 28 '14 19:09

Emax


Video Answer


2 Answers

The problem is that nothing is persuading the second grid column (gridx=1) to have any width, because there is no component that needs to fit only in the second column. The second column thus has 0 width, so although Button1 does straddle the first two columns, it doesn't look that way because all of its width need is satisfied by the first column; and although Button5 and Button7 straddle the second and third columns, all of their width need is satisfied by the third column.

To fix it you must persuade the buttons which should to be wider (1, 5, 7) to take up more space. Here I added padding to those buttons by setting c.ipadx = 35;. (I also removed the weightx = 1.0 constraint. For reasons I don't quite understand, it didn't work when that was left in.):

screenshot

Source:

public void init() {
    GridBagLayout gridbag = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    setLayout(gridbag);

    c.fill = c.BOTH;

    //c.weightx = 1.0;
    //c.weighty = 1.0;

    c.anchor = c.CENTER;

    c.insets.top = 5;
    c.insets.bottom = 5;
    c.insets.left = 5;
    c.insets.right = 5;

    c.gridx = 0;
    c.gridy = 0;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button1", gridbag, c);

    c.gridx = 2;
    c.gridy = 0;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button2", gridbag, c);

    c.gridx = 3;
    c.gridy = 0;
    c.gridheight = 2;
    c.gridwidth = 2;
    c.ipadx = 0;
    makebutton("Button3", gridbag, c);

    c.gridx = 0;
    c.gridy = 1;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button4", gridbag, c);

    c.gridx = 1;
    c.gridy = 1;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button5", gridbag, c);

    c.gridx = 0;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button6", gridbag, c);

    c.gridx = 1;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 2;
    c.ipadx = 35;
    makebutton("Button7", gridbag, c);

    c.gridx = 3;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button8", gridbag, c);

    c.gridx = 4;
    c.gridy = 2;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.ipadx = 0;
    makebutton("Button9", gridbag, c);
}

Edit: As pointed out in the comments, the above approach is not suitable because it prevents the layout being resized dynamically. To have the layout expand to fill the size of its container, the weightx and weighty constraints are needed, but then the second column does not get any width.

Here is an attempt at an alternative solution. It's a dirty hack that inserts an invisible component at the bottom of the second column to force the column to have width:

    c.gridx = 1;
    c.gridy = 3;
    c.gridheight = 1;
    c.gridwidth = 1;
    c.insets.set(0, 0, 0, 0);
    c.weighty = 0;
    add(Box.createRigidArea(new Dimension(50, 0)), c);

This copes fairly well when the window is resized because although the component is given a fixed initial size, GridBagLayout scales up it proportionally with the other components. It is still not perfect, though. Maybe there is a better solution but I can't find it.

like image 91
Boann Avatar answered Oct 09 '22 07:10

Boann


I managed to design the needed layout without any hack and supporting dynamic resizing by using JGoodies FormLayout:

import java.awt.Component;

import javax.swing.JButton;
import javax.swing.JPanel;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

public class FormLayoutPanel extends JPanel
    {
    public FormLayoutPanel()
        {
        setAlignmentY( Component.BOTTOM_ALIGNMENT );
        setAlignmentX( Component.RIGHT_ALIGNMENT );
        setLayout( new FormLayout( new ColumnSpec[] {
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "25px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ),
            FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
            ColumnSpec.decode( "41px:grow" ), },
            new RowSpec[] {
                RowSpec.decode( "25px:grow" ),
                FormFactory.LINE_GAP_ROWSPEC,
                RowSpec.decode( "25px:grow" ),
                FormFactory.LINE_GAP_ROWSPEC,
                RowSpec.decode( "25px:grow" ), } ) );

        JButton button1 = new JButton( "1" );
        add( button1, "1, 1, 3, 1, fill, fill" );
        JButton button2 = new JButton( "2" );
        add( button2, "5, 1, fill, fill" );
        JButton button3 = new JButton( "3" );
        add( button3, "7, 1, 3, 3, fill, fill" );
        JButton button4 = new JButton( "4" );
        add( button4, "1, 3, fill, fill" );
        JButton button5 = new JButton( "5" );
        add( button5, "3, 3, 3, 1, fill, fill" );
        JButton button6 = new JButton( "6" );
        add( button6, "1, 5, fill, fill" );
        JButton button7 = new JButton( "7" );
        add( button7, "3, 5, 3, 1, fill, fill" );
        JButton button8 = new JButton( "8" );
        add( button8, "7, 5, fill, fill" );
        JButton button9 = new JButton( "9" );
        add( button9, "9, 5, fill, fill" );
        }
    }
like image 40
Gerold Broser Avatar answered Oct 09 '22 05:10

Gerold Broser