michael nesterenko
michael nesterenko

Reputation: 14439

GridBagLayout and minimum width

I want to make panel with constrained maximum width, but which reduces its width when container becomes shorter.

I used GridBagLayout but it behaves weirdly when size becomes short enough.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @author Michael Nesterenko
 *
 */
public class SSCE extends JFrame {

    /**
     * 
     */
    public SSCE() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GridBagLayout gbl = new GridBagLayout();
        gbl.columnWidths = new int[] {200, 1};
        gbl.columnWeights = new double[] {0, 1};
        gbl.rowHeights = new int[] {10};
        gbl.rowWeights = new double[] {0};
        setLayout(gbl);

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;

        JPanel sizeRestrictedPanel = new JPanel();
        sizeRestrictedPanel.setBackground(Color.BLUE);
        sizeRestrictedPanel.setMinimumSize(new Dimension(50, 50));
        sizeRestrictedPanel.setMaximumSize(new Dimension(300, 50));
        sizeRestrictedPanel.setPreferredSize(new Dimension(300, 50));
        add(sizeRestrictedPanel, gbc);

        JPanel dummy = new JPanel();
        dummy.setBackground(Color.RED);
        add(dummy, gbc);

        setPreferredSize(new Dimension(600, 200));
        pack();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new SSCE().setVisible(true);
    }

}

When frame width becomes short enough blue panel is instantly resized, however I want it to be resized smoothly with window resizing.

Upvotes: 2

Views: 3704

Answers (2)

Thorn
Thorn

Reputation: 4057

When the window's width is reduced by the user, only the red panel shrinks at first.

The code example from the question is actually starting with an expanded window beyond the size given by packing the components. If we remove the line setPreferredSize(new Dimension(600, 200)); then we get the window shown below instead of a window with an expanded red panel. If we reduce the width to less than this size, then we are forcing the blue panel to be smaller than its preferred size and "it behaves weirdly." This is because since GridBagLayout can no longer honor the blue panels preferred size, it now gives each panel equal space and just attempts to honor their minimum sizes.

enter image description here

I recommend not using setPreferredSize with GridBagLayout. You may wish to determine the minimum dimensions required for your window to still be useful and not allow the user to reduce the size below this minimum. Some components should not occupy more space than they are originally assigned when the user expands the window. We can accomplish this using GridBagConstraints weightx and weighty instead of setMaximumSize.

The code below shows the two panels resizing smoothly and I added some text to display the dimensions as they get resized.

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

/**
 * @author Michael Nesterenko, Leon LaSpina
 *
 */
public class SSCE extends JFrame {
   JLabel blueDimension, redDimension;
   JPanel sizeRestrictedPanel, dummyPanel, bottomPanel;

   public SSCE() {
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      JPanel testPanel = new JPanel();
      bottomPanel = new JPanel();
      setLayout(new BorderLayout());
      GridBagLayout gbl = new GridBagLayout();
      testPanel.setLayout(gbl);
      add(testPanel, BorderLayout.CENTER);
      add(bottomPanel, BorderLayout.SOUTH);
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.fill = GridBagConstraints.HORIZONTAL;
      gbc.weightx = 0.75;

      sizeRestrictedPanel = new JPanel();
      sizeRestrictedPanel.setBackground(Color.BLUE);
      sizeRestrictedPanel.setMinimumSize(new Dimension(50, 50));
      sizeRestrictedPanel.setMaximumSize(new Dimension(300, 50));
      //sizeRestrictedPanel.setPreferredSize(new Dimension(300, 50));
      testPanel.add(sizeRestrictedPanel, gbc);
      dummyPanel = new JPanel();
      dummyPanel.setBackground(Color.RED);
      dummyPanel.setMinimumSize(new Dimension(50, 50));
      //dummyPanel.setPreferredSize(new Dimension(50, 50));
      gbc.weightx = 0.25;
      testPanel.add(dummyPanel, gbc);

      setSize(new Dimension(600, 200));
      blueDimension = new JLabel("------");
      blueDimension.setForeground(Color.BLUE);
      redDimension = new JLabel("------");
      redDimension.setForeground(Color.RED);
      bottomPanel.add(blueDimension);
      bottomPanel.add(new JLabel("   "));
      bottomPanel.add(blueDimension);
      bottomPanel.add(redDimension);
      this.addComponentListener(new ComponentAdapter() {
         public void componentResized(ComponentEvent e) {
            updateDimensionText();
         }
      });
   }

   private void updateDimensionText() {
      Dimension d1 = sizeRestrictedPanel.getSize();
      String s1 = d1.width + "," + d1.height;
      Dimension d2 = dummyPanel.getSize();
      String s2 = d2.width + "," + d2.height;
      blueDimension.setText(s1);
      redDimension.setText(s2);
   }

   /**
    * @param args
    */
   public static void main(String[] args) {
      SSCE win = new SSCE();
      win.setVisible(true);
      win.updateDimensionText();
   }
}

Upvotes: 2

StanislavL
StanislavL

Reputation: 57381

You can define GridBagConstraints.ipadx and GridBagConstraints.ipady constraints to set min width/height

/**
 * This field specifies the internal padding of the component, how much
 * space to add to the minimum width of the component. The width of
 * the component is at least its minimum width plus
 * <code>ipadx</code> pixels.
 * <p>
 * The default value is <code>0</code>.
 * @serial
 * @see #clone()
 * @see java.awt.GridBagConstraints#ipady
 */
public int ipadx;

/**
 * This field specifies the internal padding, that is, how much
 * space to add to the minimum height of the component. The height of
 * the component is at least its minimum height plus
 * <code>ipady</code> pixels.
 * <p>
 * The default value is 0.
 * @serial
 * @see #clone()
 * @see java.awt.GridBagConstraints#ipadx
 */
public int ipady;

Upvotes: 3

Related Questions