2

I noticed something weird with setting maximum sizes in a boxlayout.

I need a column of panels running down the right side of a window, and I tried to set it up with a box layout. There might be 8-10 or there might be 30-40, so I give them enough space to account for 30-40, but if there's only 8-10 they spread out to take up all the available space and it looks pretty weird. So I figured I'll setMaximumSize for them to stop that from happening...

...and I kept ending up with most of them disappearing.

So I broke it down into a really basic stack of colored panels, trying to see what's going on, and I've figured out how to carry on, but I don't like it.

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

public class BoxLayoutDemo extends JFrame {


  public BoxLayoutDemo() {
    super("JScrollPane Demonstration");
    setSize(800, 600);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    init();
    setVisible(true);
  }

  public void init() {
    setLayout(null);

    JPanel rightPanel = new JPanel();
    rightPanel.setBounds(400,0,400,600);
    rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));

    JPanel greenPanel = new JPanel();
    JPanel bluePanel = new JPanel();
    JPanel yellowPanel = new JPanel();
    greenPanel.setBackground(Color.GREEN);
    bluePanel.setBackground(Color.BLUE);
    yellowPanel.setBackground(Color.YELLOW);

    rightPanel.add(greenPanel);
    rightPanel.add(bluePanel);
    rightPanel.add(yellowPanel);

    add(rightPanel);



  }

  public static void main(String args[]) {
    new BoxLayoutDemo();
  }
}

...that gets you just what I'd expect: Three colored boxes taking up the right half of the screen.

If I add something like:

greenPanel.setMaximumSize(new Dimension(400,100));
bluePanel.setMaximumSize(new Dimension(400,100));
yellowPanel.setMaximumSize(new Dimension(400,100));

Then instead the three colored boxes are each only 100px tall and only take up the top half or so of the screen, which is also what I'd expect.

But if I do this...

greenPanel.setMaximumSize(new Dimension(400,100));
yellowPanel.setMaximumSize(new Dimension(400,100));

The blue panel crushes both the other two down to only a couple of px tall.

This probably isn't going to be a problem, I can just set a maximum size for everything, but in a hypothetical situation where that isn't really feasible, is there a way to alter this behavior, or is this just what box layout does?

EDIT:

Okay, so we'll call test1 this:

greenPanel.setMinimumSize(new Dimension(400,100));
yellowPanel.setMinimumSize(new Dimension(400,100));

...which has no effect on anything since the green and yellow panels are about 200 px high anyway.

test2:

greenPanel.setMaximumSize(new Dimension(400,100));
yellowPanel.setMaximumSize(new Dimension(400,100));

...causes the blue panel to crowd out the green and yellow ones as originally described.

test3:

greenPanel.setMinimumSize(new Dimension(400,100));
greenPanel.setMaximumSize(new Dimension(400,100));
yellowPanel.setMinimumSize(new Dimension(400,100));
yellowPanel.setMaximumSize(new Dimension(400,100));

...SHOULD result in green and yellow panels that are 100 px tall, as you described, except that in practice what actually happens is the exact same thing as in test2.

user1299656
  • 630
  • 1
  • 9
  • 15
  • don't hard-code sizes, ever. Never even think about a null layout nor interfering with component's sizing hints (http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi/7229519#7229519). Choose a LayoutManager that serves your needs and allows fine-tuning, f.i. MigLayout (or if you are stuck with core managers, GridBagLayout). – kleopatra Jul 14 '12 at 08:42
  • 1
    Yeah, yeah the first rule of java club. Except layout managers won't actually make visual stuff scale nicely unless I take extra measures to the point it would work with a null layout anyway. I'm not interested in religious attitudes towards programming conventions. – user1299656 Jul 14 '12 at 17:16
  • shrugs, it's _your_ time you are wasting in insisting doing the-wrong-thing ... – kleopatra Jul 15 '12 at 08:35

1 Answers1

1

The problem is, the default max size of the bluePane is now 32767x32767...

The layout manager basically goes and tries to offer the maximum amount of space it can to blue (the default minimum size seems to be 10x10 on my PC (and so is the default preferred size))

If instead of using setMaximumSize, I change your code to use the minimumSize

greenPanel.setMinimumSize(new Dimension(400,100));
yellowPanel.setMinimumSize(new Dimension(400,100));

I can get the desired results, because the layout manager can no longer assign more space to the blue pane.

UPDATE

Then I'm missing something.

If I use your default code, I get all three panels set out normally. If I only use green & yellow (max size), then they get squished as you describe If I set the green & yellows min size, I get the three panels set out normally

Here's the code I was using.

public void init() {

    setLayout(null);

    JPanel rightPanel = new JPanel();
    rightPanel.setBounds(400,0,400,600);
    rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));

    JPanel greenPanel = new JPanel();
    JPanel bluePanel = new JPanel();
    JPanel yellowPanel = new JPanel();

      Dimension size = new Dimension(400, 100);

      // Default
    //    greenPanel.setMaximumSize(size);
    //    bluePanel.setMaximumSize(size);
    //    yellowPanel.setMaximumSize(size);

      // Test 1
    //    greenPanel.setMaximumSize(size);
    //    yellowPanel.setMaximumSize(size);

      // Test 2
      greenPanel.setMinimumSize(size);
      yellowPanel.setMinimumSize(size);

    greenPanel.setBackground(Color.GREEN);
    bluePanel.setBackground(Color.BLUE);
    yellowPanel.setBackground(Color.YELLOW);

    rightPanel.add(greenPanel);
    rightPanel.add(bluePanel);
    rightPanel.add(yellowPanel);

    add(rightPanel);

  }

Your default

Your default setup

Green & Yellow Max Only (Blue default sizes)

Test 1 - Green & Yellow Max only

Green & Yellow Min Only (Blue default sizes)

Test 2 - Green & Yellow Min only

Now take a serious think about what's going on.

Under the default test, the layout manager has determined that it can layout, proportionally all the panels (because the heights are the same). It has to do this, because there max sizes have been set it & it has the space to do so. In fact, if I don't set any of there sizes at all (all default), they layout this way

Under test 1, it's decided that the blue pane requires proportionally more space then green and yellow (Blue MAX height = 32767, Green & Yellow MAX height = 100), hence it squishes them down (Green & Yellows min heights are 10 pixels)

Under test 2, it's decided that the blue pane should receive the most amount of size (as it's MAX size is 32767, but's min and pref sizes are 10), but it's also found that the green and yellow panes can not be smaller then 100 pixels, so it allocates the remaining space over to blue (which is about 100 pixels in this case).

UPDATE 2

Okay, here's what I've worked out :P. Basically, the difference between using only the min or only the max is coming down to the default size of these sizes (min/max/pref).

When you're using only the min, the total combined max height is 98301 (each components max been 32767). This needs to be divided among the components. The layout uses a factoring approach (supplying a % of the space to all the components based on needs). To do this, it use a combination of the max and pref sizes.

When I only used the min size, the green and yellow where actually been allocated 200 pixels - this came down to the max size value. Using only the max size, the green and yellow where allocated 11 pixels (because blue got the lion share).

... So yes, the min sizes are been ignored ... in the case.

The layout manager uses this path if the amount of allocated space (600) is >= the total preferred space (30). If the allocated space (600) is < the total preferred space, the layout manager will use a combination of pref/min size to calculate the factoring...

The docs actually say that the layout managers may ignore one or more of these (max/min/pref) values as they are simply a guide line.

However, if used the pref size instead, the blue and green where allocated 229 pixels (with blue getting only 140).

In this case, I'd go for a combination of max & pref sizes or use something like the GridBagLayout.

I've not used it, but many swear by the MigLayout.

Hay, thanks for a fun question ;)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Even if that worked, it would be a less than ideal solution, but it doesn't work. Setting those minimums for green and yellow produces the exact same result as not setting any sizes at all, since they're bigger than that anyway. If I set both the minimum and the maximum on green and yellow to 400,100 but don't do anything with the blue then I get the same results as before. The blue panel crowds out the other two, with their minimum sizes apparently being ignored. – user1299656 Jul 14 '12 at 17:34
  • See edit, no paragraph structure in comments makes reading them difficult. – user1299656 Jul 14 '12 at 22:58
  • Cheers that some more info to go by – MadProgrammer Jul 15 '12 at 09:31