Understanding GridBagLayout constraints

2019-04-02 08:20发布

问题:

I am relatively new to swing and I am trying to figure out exactly how it works. Tell me if I am wrong.

I have mostly figured out gridx and gridy which is necessary to place a component. You need at least n values of (gridx,gridy) to create an nxn grid. For example (5,5),(3,3),(4,9),(3,10) will create a 3x4 gridspace(4 rows, 3 columns) with the components using the above (gridx,gridy) respectively placed in cells (3,2),(1,2),(2,3),(1,4).

weightx and weighty seems to have 2 functions, a >0 value of weightx and weighy stretches the grid cells to the edges(otherwise it's centralised) and we can also set proportions to size of the component - so if one component has gridx=0.1 and anothr has 0.2, then the later one is likely to be twice as wide. However, while proportioning components, the minimum default width and height of a component is respected.

fill is required to stretch a component to the edges of the cells. Without fill, the component will remain at the center.

but we can use anchor in such cases to position the component say along the north west corner of the cell instead of center.

insets create a wall of space inside the edges of the cell.

ipadx and ipady pushes the boundaries of the column or row containing the cell.

But I am not able to figure out very well how gridwidth and gridheight works.

Consider this example below.Here 4 buttons are placed in cells b1(3,2),b2(1,1),b3(2,3),b4(4,4) of 4x4 gridspace.

How do I make the buttons , say b2 or b4, occupy the whole row or column of the cell that it is occupying?

import javax.swing.*;
import java.awt.*;
//import java.awt.event.*;
public class Swing29a
{
public static void main(String[] args)
{
JFrame f1= new JFrame("GridBag Layout Test");

f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setResizable(true);
f1.setLocation(200,100);
f1.setSize(800,800);

JPanel p1 = new JPanel();
p1.setBackground(Color.black);
f1.add(p1);


JButton b1= new JButton("Button 1");
b1.setBackground(Color.white);

JButton b2= new JButton("Button 2");
b2.setBackground(Color.white);

JButton b3= new JButton("Button 3");
b3.setBackground(Color.white);

JButton b4= new JButton("Button 4");
b4.setBackground(Color.white);



GridBagLayout gm1= new GridBagLayout();
p1.setLayout(gm1);
GridBagConstraints cns =new GridBagConstraints();

cns.gridx=5;
cns.gridy=5;
cns.weightx=0.1;
cns.weighty=0.1;
cns.fill=GridBagConstraints.BOTH;

p1.add(b1,cns);

cns.gridx=3;
cns.gridy=3;
p1.add(b2,cns);


cns.gridx=4;
cns.gridy=9;
p1.add(b3,cns);

cns.gridx=7;//3;
cns.gridy=10;
cns.gridheight=3;
cns.weightx=0.2;
cns.weighty=0.2;
//cns.weightx=10.0;
//cns.weighty=9.0;    
//cns.ipadx=50;
//cns.ipady=50;
p1.add(b4,cns);

f1.setVisible(true);

}
}

EDIT: Here is a LINK TO IMAGE http://postimg.org/image/wae2x4w4z/

I want any of the buttons to be able to fill the whole row or column, or take at least 2 cells in a row.

回答1:

gridwidth, gridheight:

Specify the number of columns (for gridwidth) or rows (for gridheight) in terms of cells the component's display area can be occupied by the component added with these constraint defined. The default value is 1.

So, If for a grid of (R x C); there are C number of cells in a row. If you want to have a component to occupy all the cell of that specific row, just set the GridBigConstraint.gridWidth to C.

Use GridBagConstraints.REMAINDER to specify that the component be the last one in its row (for gridwidth) or column (for gridheight).

There is already a nice written example in the tutorial: How to use GridBagLayout



回答2:

You mean something like this...

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridBagTest {

    public static void main(String[] args) {
        JFrame f1 = new JFrame("GridBag Layout Test");

        f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f1.setResizable(true);
        f1.setLocation(200, 100);
        f1.setSize(800, 800);

        JPanel p1 = new JPanel();
        p1.setBackground(Color.black);
        f1.add(p1);

        JButton b1 = new JButton("Button 1");
        b1.setBackground(Color.white);

        JButton b2 = new JButton("Button 2");
        b2.setBackground(Color.white);

        JButton b3 = new JButton("Button 3");
        b3.setBackground(Color.white);

        JButton b4 = new JButton("Button 4");
        b4.setBackground(Color.white);

        GridBagLayout gm1 = new GridBagLayout();
        p1.setLayout(gm1);
        GridBagConstraints cns = new GridBagConstraints();

        cns.gridx = 5;
        cns.gridy = 5;
        cns.weightx = 0.1;
        cns.weighty = 0.1;
        cns.fill = GridBagConstraints.BOTH;

        p1.add(b1, cns);

        cns.gridx = 3;
        cns.gridy = 3;
//        cns.gridheight = GridBagConstraints.REMAINDER;
        cns.gridwidth = 3;
        p1.add(b2, cns);

        cns.gridheight = 1;
        cns.gridwidth = 1;
        cns.gridx = 4;
        cns.gridy = 9;
        p1.add(b3, cns);

        cns.gridx = 6;
        cns.gridy = 3;
        cns.gridheight = 7;
        cns.weightx = 0.2;
        cns.weighty = 0.2;
//        cns.gridheight = 4;
        p1.add(b4, cns);

        f1.setVisible(true);

    }
}

gridwidth basically tells GridBagLayout how many columns a component should expand across (the default being 1). This will always expand right.

gridheight does the same, expect that it will always expand down...

Updated

GridBagLayout is very powerful, but even then, sometimes, it has limitations.

To achieve something like...

The simplest choice is to addd a "filler" component, for example...

cns.gridx = 3;
cns.gridy = 9;
cns.gridwidth = 1;
JPanel pnl = new JPanel();
pnl.setOpaque(false);
p1.add(pnl, cns);


回答3:

I said I want something like more or less like this: http://postimg.org/image/7a5vi8t21/

and thanks to all the clarifications I am able to do more or less that. I used an extra transparent button. here is the ouput image: http://postimg.org/image/6yw3c8b37/

and below is the code

import javax.swing.*;
import java.awt.*;
//import java.awt.event.*;

public class GridBagTest2 
{

    public static void main(String[] args) {
        JFrame f1 = new JFrame("GridBag Layout Test");

        f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f1.setResizable(true);
        f1.setLocation(200, 100);
        f1.setSize(800, 800);

        JPanel p1 = new JPanel();
        p1.setBackground(Color.black);
        f1.add(p1);

        JButton b1 = new JButton("Button 1");
        b1.setBackground(Color.white);

        JButton b2 = new JButton("Button 2");
        b2.setBackground(Color.white);

        JButton b3 = new JButton("Button 3");
        b3.setBackground(Color.white);

        JButton b4 = new JButton("Button 4");
        b4.setBackground(Color.white);

        JButton b5 = new JButton("        ");
        b5.setBackground(Color.white);
        b5.setBorderPainted(false);
        b5.setOpaque(false);

        JLabel lb1 = new JLabel("");
        //lb1.setOpaque(true);

        GridBagLayout gm1 = new GridBagLayout();
        p1.setLayout(gm1);
        GridBagConstraints cns = new GridBagConstraints();

        cns.gridx = 5;
        cns.gridy = 5;
        cns.weightx = 0.1;
        cns.weighty = 0.1;
        cns.fill = GridBagConstraints.BOTH;

        p1.add(b1, cns);

        cns.gridx = 3;
        cns.gridy = 3;

        cns.gridwidth = 3;
        p1.add(b2, cns);

        cns.gridheight = 1;
        cns.gridwidth = 1;
        cns.gridx = 4;
        cns.gridy = 9;
        p1.add(b3, cns);

        cns.gridx = 7;
        cns.gridy = 3;
        cns.gridheight = 8;
        cns.weightx = 0.2;
        cns.weighty = 0.2;

        p1.add(b4, cns);


        cns.gridx = 3;
        cns.gridy = 10;
        cns.gridheight=1;
        cns.gridwidth = 1;
        cns.weightx = 0.1;
        cns.weighty = 0.1;
        p1.add(b5, cns);


        f1.setVisible(true);

    }
}

I think I am finally understanding how gridwidth and gridheight works. They work from left to right and top to down. They also collapse in the absense of supporting components in empty rows or columns.

however, there are still some questions I don't understand. If I use a transparent label (lb1) instead of the transparent button b5, the dimension of the column changes. Also, why is b4 not twice as wide as the other buttons despite having twice the weight?