javaswinglayoutgridbaglayoutminimum-size

How to set minimum sizes with GridBagLayout?


I have a simple GUI using GridBagLayout with a button panel at the top, and a custom resizable component taking up the rest of the space, as shown in the following image:

The GUI at start-up.

The custom component (the red one) has a preferred size of (400, 300) and a minimum size of (40, 30) and is happy to be resized to any size greater than that. However, I would like my frame to respect the minimum size of the button panel and not allow the frame to be resized such that any of the buttons are not fully shown on the screen. This is not currently the behaviour as I can resize it far past those boundaries as seen here:

The GUI resized ridiculously small.

My current code is as follows:

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

public class Example {
    public static void main(String[] args) {
        // Setup JFrame and GridBagLayout.
        JFrame frame = new JFrame("Example");
        Container contentPane = frame.getContentPane();
        GridBagLayout layout = new GridBagLayout();
        contentPane.setLayout(layout);
        layout.rowWeights = new double[] {0.0, 1.0};
        layout.columnWeights = new double[] {1.0};
        GridBagConstraints cons = new GridBagConstraints();

        // Add button panel with a BoxLayout.
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
        panel.add(new JButton("Button 1"));
        panel.add(new JButton("Button 2"));
        panel.add(new JButton("Button 3"));
        cons.anchor = GridBagConstraints.NORTHWEST;
        cons.gridx = 0;
        cons.gridy = 0;
        layout.setConstraints(panel, cons);
        contentPane.add(panel);

        // Add custom component, resizable.
        JComponent custom = new JComponent() {
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }

            public Dimension getMinimumSize() {
                return new Dimension(40, 30);
            }

            public void paintComponent(Graphics g) {
                g.setColor(Color.RED);
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        cons.gridx = 0;
        cons.gridy = 1;
        cons.fill = GridBagConstraints.BOTH;
        layout.setConstraints(custom, cons);
        contentPane.add(custom);

        // Pack and show frame.
        frame.pack();
        frame.setVisible(true);
    }
}

I have tested this on both Mac OS X 10.8 (Java 6) and Ubuntu 3.2.8 (Java 6) and observed the same thing.

How can I prevent the frame from being resized to cover any of the buttons? More generally, how can I get GridBagLayout to actually respect the minimum sizes of my components? When I print out the minimum size of my frame I get (291, 81), which is exactly what I want, but when I resize the frame, it goes beyond that.

Note: I have looked at this related question but it doesn't appear to answer my question.


Solution

  • I'm not sure why, but if I use...

    frame.setMinimumSize(frame.getMinimumSize());
    

    After the UI has being created (obviously), it works.

    I "think" it has something to do with ((WindowPeer)peer).updateMinimumSize(); in the setMinimumSize size method of Window...