OK, I have been experimenting around with GridBagLayout and I'm getting the hang of it. Things are looking the way I want them to on the INITIAL drawing of the GUI. However, when I RESIZE the JFrame to make it smaller vertically, at a certain point, the proportions get skewed. For example, in the following program, everything lays out nice originally. The blue and pink panels are twice as tall as the green and yellow panels, as I intend (see attached image). Then as I resize the JFrame to be smaller vertically, the blue and pink panels are taller than the green and yellow panels, but the ratio has changed. They are just slightly taller, but not twice as tall (see other attached image). Does anyone know why this occurs and how I can fix it so the ratios remain uniform when resizing?

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

public class GridBagExperiment extends JFrame {
	JPanel redPanel, bluePanel, greenPanel, yellowPanel, pinkPanel,
            orangePanel, grayPanel, cyanPanel, magentaPanel, blackPanel;


    double col1Weight = 0.25;
    double col2Weight = 0.25;
    double col3Weight = 0.25;
    double col4Weight = 0.25;
    double col5Weight = 0.25;


    double row1Weight = 0.25;
    double row2Weight = 0.25;
    double row3Weight = 0.25;
    double row4Weight = 0.25;

    GridBagConstraints gbc;
    Container container;

    public static void main (String args[]) {
        GridBagExperiment gbe = new GridBagExperiment();
    }

    public GridBagExperiment() {
        setSize (400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        container = getContentPane();

        redPanel = new JPanel ();
        bluePanel = new JPanel ();
        greenPanel = new JPanel ();
        yellowPanel = new JPanel ();
        pinkPanel = new JPanel ();
        orangePanel = new JPanel ();
        grayPanel = new JPanel ();
//		cyanPanel = new JPanel ();
//		magentaPanel = new JPanel ();
//		blackPanel = new JPanel ();

        redPanel.setBackground(Color.RED);
        bluePanel.setBackground(Color.BLUE);
        greenPanel.setBackground(Color.GREEN);
        yellowPanel.setBackground(Color.YELLOW);
        pinkPanel.setBackground(Color.PINK);
        orangePanel.setBackground(Color.ORANGE);
        grayPanel.setBackground(Color.GRAY);
 //       cyanPanel.setBackground(Color.CYAN);
 //       magentaPanel.setBackground(Color.MAGENTA);
 //       blackPanel.setBackground(Color.BLACK);

        GridBagLayout gbl = new GridBagLayout();
        container.setLayout(gbl);
        gbc = new GridBagConstraints ();

        AddPanel (redPanel, 0, 0, 2, 3, 0.0, 0.0);
        AddPanel (bluePanel, 2, 0, 1, 2, 0.0, 0.0);
        AddPanel (greenPanel, 2, 2, 1, 1, 0.0, 0.0);
        AddPanel (yellowPanel, 3, 0, 1, 1, 0.0, 0.0);
        AddPanel (pinkPanel, 3, 1, 1, 2, 0.0, 0.0);
        AddPanel (orangePanel, 0, 3, 1, 1, 0.0, 0.0);
        AddPanel (grayPanel, 1, 3, 3, 1, 0.0, 0.0);

        gbl.columnWeights = new double[] { col1Weight, col2Weight, col3Weight, col4Weight/*, col5Weight*/ };
        gbl.rowWeights = new double[] { row1Weight, row2Weight, row3Weight, row4Weight };
        setVisible (true);
    }

    public void AddPanel (JPanel panel, int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty) {
        gbc.gridx = gridx;
        gbc.gridy = gridy;
        gbc.gridwidth = gridwidth;
        gbc.gridheight = gridheight;
        gbc.weightx = weightx;
        gbc.weighty = weighty;
        gbc.fill = GridBagConstraints.BOTH;
        add(panel, gbc);
    }
}

Recommended Answers

All 8 Replies

I'm not certain, but I think you are simply hitting up against some "minimum size" type restrictions. As you can see the orange (dark yellow?) square is the same size as the green and yellow squares and it's relation to the red square has become even more skewed than the other relations, but it still has the same size as the yellow and green. In any case, the code is correct, and I don't know of any other way to "do it" that would have any chance of changing what you're seeing.

Sorry. I won't, at this point, be able to contribute anything else to this thread. ;-)

Thanks masijade. I hadn't thought of the minimum height issue (and I hadn't realized there was one for JPanels), but after some experimentation, that's definitely part of the problem. It turns out that it wasn't displaying perfectly even in the initial display. The blue height wasn't double the green height. What IS exactly a 2 to 1 ratio is this:

(actual blue height - minimum blue height) / (actual green height - minimum green height)

So that is what is going on. That said, does anyone know how to make it so that:

actual blue height / actual green height

is constant?


Revised code is below. Here is the text output, before and after resize:

Blue Minimum : 10.0 Actual : 178.0
Green Minimum : 10.0 Actual : 94.0
Blue / Green Actual Ratio = 1.8936170212765957
Blue / Green Adjusted Ratio = 2.0


Blue Minimum : 10.0 Actual : 22.0
Green Minimum : 10.0 Actual : 16.0
Blue / Green Actual Ratio = 1.375
Blue / Green Adjusted Ratio = 2.0

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

public class GridBagExperiment extends JFrame implements ComponentListener
{
    JPanel redPanel, bluePanel, greenPanel, yellowPanel, pinkPanel,
            orangePanel, grayPanel, cyanPanel, magentaPanel, blackPanel;


    double col1Weight = 0.25;
    double col2Weight = 0.25;
    double col3Weight = 0.25;
    double col4Weight = 0.25;
    double col5Weight = 0.25;


    double row1Weight = 0.25;
    double row2Weight = 0.25;
    double row3Weight = 0.25;
    double row4Weight = 0.25;

    GridBagConstraints gbc;
    Container container;



    public static void main (String args[]) {
        GridBagExperiment gbe = new GridBagExperiment();
    }


    public GridBagExperiment() {
        setSize (400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        container = getContentPane();

        redPanel = new JPanel ();
        bluePanel = new JPanel ();
        greenPanel = new JPanel ();
        yellowPanel = new JPanel ();
        pinkPanel = new JPanel ();
        orangePanel = new JPanel ();
        grayPanel = new JPanel ();
//		cyanPanel = new JPanel ();
//		magentaPanel = new JPanel ();
//		blackPanel = new JPanel ();


        redPanel.setBackground(Color.RED);
        bluePanel.setBackground(Color.BLUE);
        greenPanel.setBackground(Color.GREEN);
        yellowPanel.setBackground(Color.YELLOW);
        pinkPanel.setBackground(Color.PINK);
        orangePanel.setBackground(Color.ORANGE);
        grayPanel.setBackground(Color.GRAY);
 //       cyanPanel.setBackground(Color.CYAN);
 //       magentaPanel.setBackground(Color.MAGENTA);
 //       blackPanel.setBackground(Color.BLACK);

        GridBagLayout gbl = new GridBagLayout();
        container.setLayout(gbl);
        gbc = new GridBagConstraints ();

        AddPanel (redPanel, 0, 0, 2, 3, 0.0, 0.0);
        AddPanel (bluePanel, 2, 0, 1, 2, 0.0, 0.0);
        AddPanel (greenPanel, 2, 2, 1, 1, 0.0, 0.0);
        AddPanel (yellowPanel, 3, 0, 1, 1, 0.0, 0.0);
        AddPanel (pinkPanel, 3, 1, 1, 2, 0.0, 0.0);
        AddPanel (orangePanel, 0, 3, 1, 1, 0.0, 0.0);
        AddPanel (grayPanel, 1, 3, 3, 1, 0.0, 0.0);

        gbl.columnWeights = new double[] { col1Weight, col2Weight, col3Weight, col4Weight/*, col5Weight*/ };
        gbl.rowWeights = new double[] { row1Weight, row2Weight, row3Weight, row4Weight };
        setVisible (true);

        this.addComponentListener(this);
        DisplayHeightRatio ();
    }

    
    public void AddPanel (JPanel panel, int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty) {
        gbc.gridx = gridx;
        gbc.gridy = gridy;
        gbc.gridwidth = gridwidth;
        gbc.gridheight = gridheight;
        gbc.weightx = weightx;
        gbc.weighty = weighty;
        gbc.fill = GridBagConstraints.BOTH;
        add(panel, gbc);
    }


    public void DisplayHeightRatio ()
    {
        double greenPanelActualHeight = greenPanel.getSize().height;
        double bluePanelActualHeight = bluePanel.getSize().height;
        double greenPanelMinHeight = greenPanel.getMinimumSize().height;
        double bluePanelMinHeight = bluePanel.getMinimumSize().height;
        double ratio = bluePanelActualHeight / greenPanelActualHeight;
        double adjustedratio = (bluePanelActualHeight - bluePanelMinHeight) / (greenPanelActualHeight - greenPanelMinHeight);

        System.out.println ("Blue Minimum : " + bluePanelMinHeight + " Actual : " + bluePanelActualHeight);
        System.out.println ("Green Minimum : " + greenPanelMinHeight + " Actual : " + greenPanelActualHeight);
        System.out.println ("Blue / Green Actual Ratio = " + ratio);
        System.out.println ("Blue / Green Adjusted Ratio = " + adjustedratio + "\n\n");
    }


    public void stateChanged(ChangeEvent e)
    {
        DisplayHeightRatio ();
    }

    public void componentResized(ComponentEvent e) {
        DisplayHeightRatio ();
    }

    public void componentMoved(ComponentEvent e) {
    }

    public void componentShown(ComponentEvent e) {
    }

    public void componentHidden(ComponentEvent e) {
    }
}

I've had the same issue and found answers nowhere. My best solution has been to add preferred sizes to everything using a pixel ruler to find out sizes from the initial gui load. It's still not perfect though and had other problems, though the new problems are less commonly a problem. It's no fun, but you could revoke the ability to resizee the gui so it never has a chance to change.

I didn't look at your code or anything, but if you can set a preferred size to the largest component of your gui set, the rest should then perform weight adjustments around that gui as best as possible to maintain that single preferred size. I think of it as like nailing the largest piece to a wall so the rest have something solid to work against, you know?

Within the limits set by the individual components' min/max sizes, GridBagLayout distributes the available space according to the x/y weights - the higher the weight the more of the available space goes to that component. If you set all the weights equal then, within the min/max constraints, the window should scale proportionally.
In most cases you will want some non-porportional behaviour - eg if you have a list box with buttons under it you want the space for the buttons to remain constant and all the rest of the space to go to the list box. In that case the list box would have xweight of 1 and the buttons zero.

@Hauth don't you think that after 2 years the issue is either solved or long time abandoned?

Damn! I missed that too. Sorry.

HI!
You just have to initially set the preferredSize of all the components to 0.

From doc:
If columnWeights[i] > weight for column i, then column i is assigned the weight in columnWeights[i].

Antonio, although your solution may help, the thread is over 5 years old.

Therefore your solution no matter how good it is, is useless now.

When you post in a thread, check the original posts date to see if it's an appropriate thread to post in first.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.