Containers and Components in Swing
Calling container.setLayout(null) removes the layout manager, so the programmer takes complete responsibility for positioning and sizing the components in that container.
Predicting Where a Button Lands
Most Swing code never asks where a button should go. The container chooses for you, using a layout manager. This article looks at the opposite case: a container that has no layout manager at all. In that case, every position and size on screen is a decision the programmer has to make explicitly.
What do you think happens?
You expect an OK button near the top-left corner of a panel, but it appears far lower and to the right. The panel has no layout manager. Which line should you check first?
Reveal answer
The line that calls setBounds on the OK button
With a null layout, nothing else moves the component, so the setBounds call on the component is the only place that can have set its position. Keep this prediction in mind as you read the rest of the article, and check whether you would still choose the same line after tracing the calls.
Who Places Components With and Without a Layout Manager
The important shift is in who makes decisions. With a layout manager, the container makes those decisions and the programmer describes the arrangement in general terms. With a null layout, the programmer makes every decision explicitly. Calling container.setLayout(null) removes the layout manager, so the programmer takes complete responsibility for positioning and sizing the components in that container.
Once the layout manager is null, nothing in the container will move a component to fit a new window size or to make room for another component. If a component needs a particular spot, you must give it that spot. The diagram above shows the responsibility moving from the container to the programmer; the rest of this article is about how that responsibility is carried out.
Coordinates Inside a Container
Once the layout manager is null, the component itself carries the placement information. A component is placed with comp.setBounds(x, y, width, height). The first two values give the top-left corner of the component within its container, and the last two give its width and height. The method is always written on a component, never on the container.
The first two values describe where the top-left corner sits inside the container, measured from the container's own top-left corner. The last two values describe how large the component is. Read together, the four numbers describe a rectangle that the component occupies within its parent. The order of the four arguments is fixed, and the compiler does not check it, so a call with swapped values still compiles and simply produces a different rectangle.
- The panel is created first, as the container that will hold the button.
setLayout(null)removes the panel's layout manager, so no layout manager places the button.setBoundsis called on the button, not the panel, and supplies x, y, width and height in that order.- add places the button inside the panel after its bounds have been set.
Reading one setBounds call
Given ok.setBounds(20, 15, 80, 30) inside a panel with a null layout, what is the button's position and size?
- 1Identify the component
The call is written on ok, so the button is the component being placed.
- 2Read x and y
x is 20 and y is 15, so the top-left corner of the button is 20 and 15 from the top-left corner of the panel.
- 3Read width and height
The button is 80 wide and 30 tall.
- 4Check the container
Because the panel's layout is null, no other code moves the button after this call.
The button occupies the rectangle that starts 20 units in from the left and 15 units down from the top of the panel, and it is 80 by 30 in size.
Tracing an Unexpected Position
When a component appears in the wrong place, the search is narrow. With a null layout there is only one place to look, because nothing else is moving the component. Trace the setLayout call, the setBounds call, and the add call, in that order, to find where the result departs from what you expected. The diagram below lays out those calls in the order they appear in the code.
- 1Find the
setLayoutcall on the container. If it is null, the programmer is responsible for every placement in that container. - 2Find the
setBoundscall on the component that looks misplaced. Check that it is written on the component and not on the container. - 3Compare the four values with the position you expected. Check that x is the horizontal offset and y is the vertical offset, since swapped values are a common cause of misplacement.
- 4Find the add call for the same component and confirm that the component was added to the container you expected.
- 5Adjust the
setBoundsvalues that differ from your expectation and run the program again.
Mistakes When Positioning Components Manually
Common mistake Swapping the x and y values in setBounds
What it looks likeok.setBounds(15, 20, 80, 30) when 20 was intended for xWhy it failsThe order of the four
setBoundsarguments is fixed and the compiler does not check it, so the call compiles and places the button in a different spot.Do this insteadWrite the arguments in the order x, y, width, height and check each one against the position you planned.
Common mistake Calling setBounds on the container instead of the component
What it looks likepanel.setBounds(20, 15, 80, 30) when the intent was to place the button
Why it failsThe method is always written on a component, never on the container. The call moves or sizes the panel, not the button.
Do this insteadCall setBounds on the button itself, such as ok.setBounds(20, 15, 80, 30).
Common mistake Expecting components to adjust when the window is resized
Why it failsWith a null layout, nothing in the container moves a component to fit a new window size.
Do this insteadDecide the bounds you need and set them explicitly, or accept that the component stays where its setBounds call placed it.
Common mistake Forgetting that the layout manager still makes decisions when setLayout(null) has not been called
Practice: Find the Source of the Misplacement
A panel has setLayout(null). The code calls ok.setBounds(15, 20, 80, 30) and then panel.add(ok). The programmer expected the button 20 units from the left edge and 15 units from the top. Which call should you examine, what is wrong with it, and what would the corrected call be?
Hints
- Start by checking whether the container has a layout manager.
- Compare the first two arguments of
setBoundswith the offsets you expected. - Remember that the compiler accepts the call even when the values are in the wrong order.
Key Takeaways
- Calling
container.setLayout(null)removes the layout manager, so the programmer takes complete responsibility for positioning and sizing the components in that container. - A component is placed with
comp.setBounds(x, y, width, height): x and y give the top-left position within the container, and width and height give its size. - The argument order in
setBoundsis fixed and is not checked by the compiler, so swapped values are a common source of misplaced components. - When a component is in the wrong place, trace the
setLayoutcall, thesetBoundscall, and the add call in that order to find where the result departs from what you expected.