Jack O'Connor
Jack O'Connor

Reputation: 195

Java, When using GridBagLayout to layout panels, adding buttons to the panels changes the sizes, how do I prevent this?

Ok so I am messing around with GridBagLayout to get to grips with it. I want to use it to layout JPanels in a JFrame but these individual panels will use different layout managers, GridBagLayout probably won't suit.

But i have a problem. If i don't add anything to the panels, all of the proportions work out perfectly as in this example:

public class RealMess extends JFrame{

private JPanel panel;

public RealMess(){
    initUI();
}

public final void initUI(){

    Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
    int width = (int) screensize.getWidth();
    int height = (int) screensize.getHeight();

    panel = new JPanel();
    panel.setLayout(new GridBagLayout());



    JPanel left = new JPanel();
    left.setBackground(Color.GREEN);

    JPanel centre = new JPanel();
    centre.setBackground(Color.PINK);

    JPanel right = new JPanel();
    right.setBackground(Color.CYAN);

    JPanel leftBottom = new JPanel();
    leftBottom.setBackground(Color.LIGHT_GRAY);
    leftBottom.setLayout(new FlowLayout(0));



    JPanel bottom = new JPanel();
    bottom.setBackground(Color.MAGENTA);

    GridBagConstraints gbc = new GridBagConstraints();

    gbc.weightx = 0.11;
    gbc.weighty = 0.9;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.anchor = GridBagConstraints.FIRST_LINE_START;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(left, gbc);

    gbc.weightx = 0.11;
    gbc.weighty = 0.1;
    gbc.anchor = GridBagConstraints.LAST_LINE_START;
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(leftBottom, gbc);

    gbc.weightx = 0.78;
    gbc.weighty = 0.9;
    gbc.anchor = GridBagConstraints.PAGE_START;
    gbc.gridx = 1;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(centre, gbc);

    gbc.weightx = 0.78;
    gbc.weighty = 0.1;
    gbc.anchor = GridBagConstraints.PAGE_END;
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(bottom, gbc);

    gbc.weightx = 0.11;
    gbc.weighty = 1;
    gbc.anchor = GridBagConstraints.FIRST_LINE_END;
    gbc.gridx = 2;
    gbc.gridy = 0;
    gbc.gridheight = 2;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(right, gbc);

    add(panel);

    setTitle("Jack");
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setExtendedState(MAXIMIZED_BOTH);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            RealMess rm = new RealMess();
            rm.setVisible(true);
        }
    });

}

}

I know that I redefined some GridBagConstraints unnecessarily but I didn't want to miss anything.

Anyway, my problem arises when i add a button to any of the panels. Like this:

public class RealMess extends JFrame{

private JPanel panel;

public RealMess(){
    initUI();
}

public final void initUI(){

    Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
    int width = (int) screensize.getWidth();
    int height = (int) screensize.getHeight();

    panel = new JPanel();
    panel.setLayout(new GridBagLayout());

    JPanel left = new JPanel();
    left.setBackground(Color.GREEN);

    JPanel centre = new JPanel();
    centre.setBackground(Color.PINK);

    JPanel right = new JPanel();
    right.setBackground(Color.CYAN);

    JPanel leftBottom = new JPanel();
    leftBottom.setBackground(Color.LIGHT_GRAY);
    leftBottom.setLayout(new FlowLayout(0));

    JButton rewind = new JButton("1");      
    rewind.setPreferredSize(new Dimension(50, 25));

    leftBottom.add(rewind);

    JPanel bottom = new JPanel();
    bottom.setBackground(Color.MAGENTA);

    GridBagConstraints gbc = new GridBagConstraints();

    gbc.weightx = 0.11;
    gbc.weighty = 0.9;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.anchor = GridBagConstraints.FIRST_LINE_START;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(left, gbc);

    gbc.weightx = 0.11;
    gbc.weighty = 0.1;
    gbc.anchor = GridBagConstraints.LAST_LINE_START;
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(leftBottom, gbc);

    gbc.weightx = 0.78;
    gbc.weighty = 0.9;
    gbc.anchor = GridBagConstraints.PAGE_START;
    gbc.gridx = 1;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(centre, gbc);

    gbc.weightx = 0.78;
    gbc.weighty = 0.1;
    gbc.anchor = GridBagConstraints.PAGE_END;
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(bottom, gbc);

    gbc.weightx = 0.11;
    gbc.weighty = 1;
    gbc.anchor = GridBagConstraints.FIRST_LINE_END;
    gbc.gridx = 2;
    gbc.gridy = 0;
    gbc.gridheight = 2;
    gbc.fill = GridBagConstraints.BOTH;

    panel.add(right, gbc);

    add(panel);

    setTitle("Jack");
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setExtendedState(MAXIMIZED_BOTH);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            RealMess rm = new RealMess();
            rm.setVisible(true);
        }
    });

}

}

The bottomLeft panel got bigger and hence the size of the grid squares related to it.

In the first example, everything is taking up a percentage of the width or height of the window dictated by:

gbc.weightx

And

gbc.weighty

Doing it this way makes it very easy to make everything the correct size.

Is there a workaround which allows me to force the panel sizes to be influenced only by the weight values?

Upvotes: 1

Views: 2713

Answers (1)

Mel Nicholson
Mel Nicholson

Reputation: 3225

weightx and weighty show the proportional assignment for space not requested by the underlying components. For example, if you have a label and a textfield oriented horizontally, you probably want the label to take a fixed amount of spaced based on the biggest label in the column, and the remainder of the space to go to the textfield. Assign all the weightx to the textfield and that is exactly what happens. The label has a weightx of zero, but is not scrunched to zero size because only the excess space is dictated by weight. Empty panels have a minimum size of zero, so all the space is considered extra.

If you want to force the layout to work as you describe, you would need to extend JPanel for the sub-panels to lie to the GridBagLayout about their contents. This could get you into trouble if you start making things smaller than their minimums.

Upvotes: 1

Related Questions