22

Hi I am using a BoxLayout to stack JPanels on top of each other (BoxLayout.Y_AXIS), for example if my parent JPanel is of height 500 pixels and I add two child panels to it both of height 100 pixels. The BoxLayout stretches them so that together they occupy the the 500px space. Does anyone know how to disable this feature?

Lukas Rotter
  • 4,158
  • 1
  • 15
  • 35
Aly
  • 15,865
  • 47
  • 119
  • 191

5 Answers5

23

BoxLayout is one of the few layout managers that respects the minimum and maximum sizes of a component. So if you want to prevent a panel from stretching you can use:

panel.setMaximumSize( panel.getPreferredSize() );
camickr
  • 321,443
  • 19
  • 166
  • 288
  • This may have been a while ago, but is that using an overridden getPreferredSize() method? – MikeM Jul 18 '14 at 12:12
  • @MikeM, no, since the panel is relying on the layout manager to return the preferred size. Actually a better solution is to extend the JPanel and override the `getMaximumSize()` method to simply return the value from the `getPreferredSize()` method. This way the maximum size will be dynamically calculated in case the preferred size dynamically changes. – camickr Jul 18 '14 at 15:11
12

Use GridBagLayout instead. You have much more control over your UI.

But if you want to use BoxLayout still, and don't want them to stretch, you can check out using invisible component fillers like rigid areas, glue and fillers.

Ascalonian
  • 14,409
  • 18
  • 71
  • 103
4

This seems to work perfectly fine... using BoxLayout, as you wanted.

test

    this.setLayout(new FlowLayout()); // this being the JFrame

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setPreferredSize(new Dimension(500, 500));
    panel.setBackground(Color.orange);
    this.add(panel); // add the parent to the JFrame

    JPanel pnlChild1 = new JPanel();
    pnlChild1.setBackground(Color.cyan);
    pnlChild1.setMaximumSize(new Dimension(200, 100));

    JPanel pnlChild2 = new JPanel();
    pnlChild2.setBackground(Color.magenta);
    pnlChild2.setMaximumSize(new Dimension(200, 100));

    panel.add(pnlChild1);
    panel.add(pnlChild2);
Armandt
  • 311
  • 1
  • 3
  • 8
4

The trick is, as the previous answer mentioned, to use the glue, fillers, and rigid areas in the box layout. Unlike that responder, though, I'd recommend sticking with BoxLayout - you can accomplish most simple UIs easier with Box than with the Grid Bag; and the extra power doesn't buy you much in your typical dialog box.

In the old idiom, these were things like Box.createHorizontalStrut(int x) and Box.createHorizontalGlue(); the idea is that you put a strut between your first and second components and then add a glue after the second one. ("strut" = "rigid area" nowadays).

M1EK
  • 820
  • 5
  • 10
  • I will agree with that for general stacking purposes the GridBagLayout may be overkill. Just suggesting it if he goes forward. – Ascalonian Feb 03 '10 at 20:23
  • I have tried putting a rigid area between the two child panels and vertical glue after the second one, put the panels are still being stretched :s – Aly Feb 03 '10 at 20:59
  • There is no such thing as an overkill :) – willcodejavaforfood Feb 04 '10 at 14:28
  • Try adding a panel container for the bottom 2 panels, then sticking those two themselves in a box... I'm not clear on the arrangement you're looking for, but you can always come up with some combination of subpanels, struts, and glue that makes things not stretch. – M1EK Feb 04 '10 at 20:30
3

Your panels are stretching because BoxLayout does not constrain each panel to its preferred size. You need to find layouts that do respect a component's preferred size, as BorderLayout's NORTH and SOUTH positions do.

Try this:

  1. Create a JPanel with a BorderLayout. Add your child component as NORTH in this JPanel.
  2. Create a second JPanel for the other child component, add it as NORTH of a BorderLayout
  3. Add the two JPanels to your BoxLayout.

Code:

JPanel panel1 = new JPanel(new BorderLayout());
panel1.add(component1, BorderLayout.NORTH);
JPanel panel2 = new JPanel(new BorderLayout());
panel2.add(component2, BorderLayout.NORTH);

JPanel boxPanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(boxPanel, BoxLayout.Y_AXIS);
boxPanel.setLayout(boxLayout);
boxPanel.add(panel1);
boxPanel.add(panel2);
David Koelle
  • 20,726
  • 23
  • 93
  • 130
  • 1
    I like this solution because it avoids messing with gridbag and modifying the components themselves both of which is a great plus. – William Jarvis Apr 27 '16 at 10:35