Question

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.

Was it helpful?

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...

OTHER TIPS

If the minimum size is set on your frame then you can add a ComponentListener to the frame and implement the componentResized method.

Like this example

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class Test {
    public static void main(String[] args) 
    {
        final JFrame frame = new JFrame("My Frame");
        frame.setMinimumSize(new Dimension(200,200));
        frame.addComponentListener( new ComponentAdapter()
        {
            public void componentResized(ComponentEvent evt)
            {
                Dimension size = frame.getSize();
                Dimension min = frame.getMinimumSize();
                if (size.getWidth() < min.getWidth())
                {
                    frame.setSize((int)min.getWidth() ,(int) size.getHeight());
                }
                if (size.getHeight() < min.getHeight())
                {
                    frame.setSize((int)size.getWidth() ,(int) min.getHeight());
                }
            }
        });
        frame.setSize(300,300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

I often have this sort of trouble with GridBagConstraints defaults: I long ago got in the habit of setting them (weightx, gridwidth, etc.) all explicitly. That usually gets GridBagLayout to respect minimum sizes for me. If anyone knows which default I'm overriding to achieve this, I'm curious :-)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top