i'm playing with GridBagLayout in java, I wrote the following code but it's not working as I expected
I expected that the first button would be placed in point (0,0) which is upper left of the frame.
secondly, I expected that the second button height and width would be twice the size of the first button height and width but they weren't.
here is the output: https://ibb.co/hDZPgx
here is the code:
import javax.swing.*;
import java.awt.*;
public class GUIJframe extends JFrame {
private JButton jb1 = new JButton("first");
private JButton jb2 = new JButton("second");
private JButton jb3 = new JButton("third");
private GridBagConstraints gbc = new GridBagConstraints();
private GridBagLayout gbl = new GridBagLayout();
public GUIJframe () {
jcb.addItem(names);
setLocation(150,150);
setSize(500,500);
setLayout(gbl);
addComponent(jb1,0,0,1,1);
addComponent(jb2,1,0,2,2);
addComponent(jb3,2,2,5,5);
setVisible(true);
}
public void addComponent (Component component, int gridx,int gridy, int width, int height) {
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = width;
gbc.gridheight = height;
gbl.setConstraints(component,gbc);
add (component);
}
}
I expected that the second button height and width would be twice the size of the first button height and width
Your expectation is wrong.
GridBagLayout cells are flexible. The width of one column does not depend on the width of other columns. It only depends on the widths of child components in it (and the insets and ipadx, if set).
If a component takes up two columns, but there is nothing else in either of those columns, there is no reason for the GridBagLayout to expand the columns any larger than necessary to accommodate the preferred width of that component.
The same is true for heights and GridBagLayout rows.
To force one component to be twice the size of another, you will need a different layout. SpringLayout can do it, though it’s not easy to use. You might find it easier to simply add a ComponentListener on the “smaller” component, and use that component’s new size as the basis for the ”larger” component‘s preferred size.
To achieve your desired result, I would use SpringLayout.
SpringLayout lets you create constraints, called Springs, which represent sizing ranges for edges, widths, and heights of components. These can depend on the size ranges of other components, or edges of the container.
SpringLayout layout = new SpringLayout();
setLayout(layout);
SpringLayout.Constraints jb1Constraints =
new SpringLayout.Constraints(jb1);
SpringLayout.Constraints jb2Constraints =
new SpringLayout.Constraints(
Spring.sum(jb1Constraints.getX(), jb1Constraints.getWidth()),
jb1Constraints.getY(),
Spring.scale(jb1Constraints.getWidth(), 2),
Spring.scale(jb1Constraints.getHeight(), 2));
SpringLayout.Constraints jb3Constraints =
new SpringLayout.Constraints(
Spring.sum(jb2Constraints.getX(),
Spring.scale(jb2Constraints.getWidth(), 0.5f)),
Spring.sum(jb2Constraints.getY(), jb2Constraints.getHeight()),
Spring.scale(jb1Constraints.getWidth(), 5),
Spring.scale(jb1Constraints.getHeight(), 5));
add(jb1, jb1Constraints);
add(jb2, jb2Constraints);
add(jb3, jb3Constraints);
// Make container big enough to hold all components.
layout.putConstraint(
SpringLayout.EAST, getContentPane(), 0,
SpringLayout.EAST, jb3);
layout.putConstraint(
SpringLayout.SOUTH, getContentPane(), 0,
SpringLayout.SOUTH, jb3);
The constraints for jb1
are the easiest: honor that component’s minimum size, prefered size, and maximum size. Location is (0, 0).
The constraints for jb2
depend on those of jb1
:
jb2
is jb1.x + jb1.width, which is effectively the right edge of jb1.The constraints for jb3
depend on both jb2 and jb1:
Finally, SpringLayout is different from other layout managers, in that it doesn’t automatically set the size of the container it’s laying out to be big enough to hold all child components. We have to do that work ourselves, by using SpringLayout.putConstraint to link the container’s right edge (EAST) to the jb3’s right edge, and the container’s bottom edge (SOUTH) to jb3’s bottom edge.