Concepts / Containers and Components in Swing

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.

  • Programming

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?

  • The line that creates the panel

  • The line that calls setLayout(null) on the panel

  • The line that calls setBounds on the OK button

  • The line that sets the window title

Reveal answer
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.

Layout manageractiveLayout managerremoved (null)Button placementcontainer decidesButton placementprogrammer decides
What changes when container.setLayout(null) replaces an active layout manager? Who is responsible for the button's position afterward?

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.

x20y15width80height30
Where does (x, y) sit relative to the container, and how does the component's rectangle map onto the container's area? The values below correspond to ok.setBounds(20, 15, 80, 30).

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.

java
Notes on the code
  • 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.
  • setBounds is 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.
Worked example

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?

  1. 1
    Identify the component

    The call is written on ok, so the button is the component being placed.

  2. 2
    Read 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.

  3. 3
    Read width and height

    The button is 80 wide and 30 tall.

  4. 4
    Check the container

    Because the panel's layout is null, no other code moves the button after this call.

Result

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.

setLayout(null)panelsetBounds(20, 15, 80,30)buttonadd(ok)panelthenthen
In what order do setLayout, setBounds and add run, and which call last set the button's position? The setBounds call is the one that controls placement.
  1. 1
    Find the setLayout call on the container. If it is null, the programmer is responsible for every placement in that container.
  2. 2
    Find the setBounds call on the component that looks misplaced. Check that it is written on the component and not on the container.
  3. 3
    Compare 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.
  4. 4
    Find the add call for the same component and confirm that the component was added to the container you expected.
  5. 5
    Adjust the setBounds values 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 like
    ok.setBounds(15, 20, 80, 30) when 20 was intended for x
    Why it fails

    The order of the four setBounds arguments is fixed and the compiler does not check it, so the call compiles and places the button in a different spot.

    Do this instead

    Write 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 like

    panel.setBounds(20, 15, 80, 30) when the intent was to place the button

    Why it fails

    The method is always written on a component, never on the container. The call moves or sizes the panel, not the button.

    Do this instead

    Call 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 fails

    With a null layout, nothing in the container moves a component to fit a new window size.

    Do this instead

    Decide 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

EASY

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 setBounds with 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 setBounds is 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 setLayout call, the setBounds call, and the add call in that order to find where the result departs from what you expected.