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:
Yellow are button name, red are row and columns.
This is what really happens:
Can anyone explain what is wrong in my code?
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.):
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.
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" );
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With