The fundamental, yet subtle assumption at play here: layout and size are directly related, 1-to-1. This is not the case, and is a common assumption in Swing programming. Size is the result of layout and size constraints.
Layout is:
- Within the space constraints you've specified
- And given the components I have to fit within that space
- Position those components in relation to one another given the specified strategy (BoxLayout, BorderLayout, etc.)
If the LayoutManager can fit the components you've given to it, without changing the overall size of the container, it will not alter the size of the container. A call to pack, on the other hand, is an explicit request to minimize the space being used. That's the basic reason you're seeing the results that you are.
Some things you might try:
- Make sure you're setting a maximum size on your components/containers, which will force size constraints on components when re-doing the layout
- Always call pack() as a habit
- Try some of the suggestions regarding common layout issues
It's tricky with Swing, because you've got to understand the painting pipeline, the layout managers, and some details of the windowing system. When it comes to the Swing documentation (and all the methods and the several different ways there are to doing any one thing) I try to read the documentation with an "assume nothing" approach, meaning, "What's the minimum possible thing that this method's documentation implies that it might do," and unless you observe additional behavior, don't get tricked into thinking that it does more than that.
Finally, I would add that the job of LayoutManagers in general is not sizing of containers so much as it is to place components in some relation to one another, according to the layout strategy (this is discussed in additional detail here). The idea is that, with the proper LayoutManager, you specify a basic layout strategy, and as a result when you resize the window they LayoutManager will intelligently move the components around so that your UI continues to follow that overall strategy. In this way layouts are basically meant to be independent of the overall size of the space in which they work, so they try not to make assumptions about what space is available - instead they take the size they are given and try to do what makes sense. Unless you explicitly put size constraints on your components, you can't guarantee what size they will be.
That means, if the LayoutManager doesn't believe that it needs to resize something in order to make it fit its overall strategy, basically it won't resize it. A call to pack, on the other hand, is an explicit request to pack things together and remove extra space.