JPanel Stabilizer
Developer's Cave July 18th. 2008, 1:42pmThis article covers a handy bit of logic to stabilize Java/Swing components that otherwise have annoying grow/shrink behavior. The (perceived) problem occurs when a Java/Swing application uses layout managers that obey internal components’ desired sizes. The layout shifts to accommodate internal components as they grow/shrink, which can cause much distress to the end user (at least it does to me).
It’s certainly desirable for Java/Swing components to grow large enough to hold their contents (labels, buttons, text fields, etc). Usually it is not known at compile time what size a panel needs to be to hold its contents, especially if it depends on user input. Specifying a fixed size is not acceptable, as it might be too small.
In these cases, the simple solution I’ve been using is to keep track of the largest size the component has ever become. Report this size as the minimum and preferred dimensions for the JComponent. When the component is used in a layout manager that obeys minimum and preferred sizing (such as BoxLayout), it will grow when needed, but never shrink, presenting a more stable experience to the user.
To make this work, getMinimumSize() and getPreferredSize() must be overridden properly. My implementation includes a Stabilizer helper class:
public final class Stabilizer { private final Dimension mLargest = new Dimension(); public Stabilizer() { } public Dimension getStableSize(Dimension superSize) { mLargest.width = Math.max(superSize.width ,mLargest.width); mLargest.height = Math.max(superSize.height, mLargest.height); return new Dimension(mLargest); // safety copy } }
Integrate the Stabilizer within a JPanel (or JComponent) implementation like this:
public class StablePanel extends JPanel { private final Stabilizer mStabilizer = new Stabilizer(); public Dimension getMinimumSize() { return mStabilizer.getStableSize(super.getMinimumSize()); } public Dimension getPreferredSize() { return getMinimumSize(); // not super } // do not override getMaximumSize() }
This panel will grow to its naturally computed size, but never report a smaller size. Do not use this technique in a component that may grow to an unmanageable size at runtime, because it will never shrink back down.












