Skip to content
Advertisement

Unexpected behavior of FlowLayout

I’m using JPanel with a default FlowLayout layout manager. I think in case the application window was resized and there is not enough width to show all components in JPanel in one row, some components will be moved to another row(s).

This assumption is based on the documentation:

If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows.

https://docs.oracle.com/javase/tutorial/uiswing/layout/flow.html

It works in some cases. For example, while using this code and decreasing window width, buttons will be located on different rows:

JavaScript

Before decreasing width -> After decreasing width

But it is enough to put one JPanel into another JPanel and layout manager stops to behave as expected:

JavaScript

Before decreasing width -> After decreasing width

I’m trying to clarify what I misunderstood.


I’ve read a lot of suggestions to use WrapLayout instead of FlowLayout. It seems reasonable, but still not clear for me why I got inconsistent behavior in the examples above.

Advertisement

Answer

JavaScript

First of all that method has been “obsolete” since JDK1.1.

The preferred approach since then is to add the “constraint” as the second parameter:

JavaScript

But it is enough to put one JPanel into another JPanel and layout manager stops to behave as expected:

The code is working as expected. The issue is your expectation.

Change the code in your first example:

JavaScript

Now, when you decrease the width the components disappear. This is because the BorderLayout.PAGE_START will respect the preferred height of the component added. The preferred height is determined by displaying all components on a single row.

But it is enough to put one JPanel into another JPanel and layout manager stops to behave as expected

When you start wrapping panels you need to understand the implications.

The FlowLayout respects the preferred size of all components added. So the components in the inner panel are all displayed in a row as expected.

When you add the outer panel to the BorderLayout.CENTER the outer panel size is adjusted, but it does not affect the inner panel because the rules of the FlowLayout, say any component added is displayed at the top of the panel. Since the inner panel is a single component, there is nothing to wrap.

This is a trick that is often used to your advantage to ensure a component retains its preferred size.

Another example. Maybe you have a horizontal GridLayout of buttons on a panel you want to add to the BorderLayout.PAGE_START.

If you add the panel directly, then the size of the button will shrink/grow as the frame with is changed.

If you want the buttons size to remain constant, you can use a “wrapper” panel. Then the “wrapper” panel size shrinks/grows, but the buttons size remains constant.

You need to understand the rules of the layout manager so you can use it effectively.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement