Download the JDK
Search the Tutorials
Hide the TOC
Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
Creating a Custom Layout Manager

> Before you start creating a custom layout manager, make sure that no existing layout manager will meet your requirements. In particular, layout managers such as `GridBagLayout`, `SpringLayout`, and `BoxLayout` are flexible enough to work in many cases. You can also find layout managers from other sources, such as from the Internet. Finally, you can simplify layout by grouping components into containers such as panels.

> > Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the `GroupLayout` layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use `GroupLayout`, then `GridBagLayout` is recommended as the next most flexible and powerful layout manager.

> To create a custom layout manager, you must create a class that implements the `LayoutManager` interface. You can either implement it directly, or implement its subinterface, `LayoutManager2`.

> Every layout manager must implement at least the following five methods, which are required by the `LayoutManager` interface:

> `void addLayoutComponent(String, Component)`
>   Called by the `Container` class's `add` methods. Layout managers that do not associate strings with their components generally do nothing in this method.

> `void removeLayoutComponent(Component)`
>   Called by the `Container` methods `remove` and `removeAll`. Layout managers override this method to clear an internal state they may have associated with the `Component`.

> `Dimension preferredLayoutSize(Container)`
>   Called by the `Container` class's `getPreferredSize` method, which is itself called under a variety of circumstances. This method should calculate and return the ideal size of the container, assuming that the components it contains will be at or above their preferred sizes. This method must take into account the container's internal borders, which are returned by the `getInsets` method.

> `Dimension minimumLayoutSize(Container)`
>   Called by the `Container` `getMinimumSize` method, which is itself called under a variety of circumstances. This method should calculate and return the minimum size of the container, assuming that the components it contains will be at or above their minimum sizes. This method must take into account the container's internal borders, which are returned by the `getInsets` method.

> `void layoutContainer(Container)`
>   Called to position and size each of the components in the container. A layout manager's `layoutContainer` method does not actually draw components. It simply invokes one or more of each component's `setSize`, `setLocation`, and `setBounds` methods to set the component's size and position.

>   This method must take into account the container's internal borders, which are returned by the `getInsets` method. If appropriate, it should also take the container's orientation (returned by the `getComponentOrientation` method) into account. You cannot assume that the `preferredLayoutSize` or `minimumLayoutSize` methods will be called before `layoutContainer` is called.

> Besides implementing the preceding five methods, layout managers generally implement at least one public constructor and the `toString` method.

> If you wish to support component constraints, maximum sizes, or alignment, then your layout manager should implement the `LayoutManager2` interface. In fact, for these reasons among many others, nearly all modern layout managers will need to implement `LayoutManager2`. That interface adds five methods to those required by `LayoutManager`:

> - `addLayoutComponent(Component, Object)`
> - `getLayoutAlignmentX(Container)`
> - `getLayoutAlignmentY(Container)`
> - `invalidateLayout(Container)`
> - `maximumLayoutSize(Container)`

> Of these methods, the most important are `addLayoutComponent(Component, Object)` and `invalidateLayout(Container)`. The `addLayoutComponent` method is used to add components to the layout, using the specified constraint object. The `invalidateLayout` method is used to invalidate the layout, so that if the layout manager has cached information, this should be discarded. For more information about `LayoutManager2`, see the `LayoutManager2` API documentation.

> Finally, whenever you create custom layout managers, you should be careful of keeping references to `Component` instances that are no longer children of the `Container`. Namely, layout managers should override `removeLayoutComponent` to clear any cached state related to the `Component`.

> ### Example of a Custom Layout

> The example `CustomLayoutDemo` uses a custom layout manager called `DiagonalLayout`. You can find the layout manager's source code in `DiagonalLayout.java`. `DialogLayout` lays out components diagonally, from left to right, with one component per row. Here is a picture of CustomLayoutDemo using `DialogLayout` to lay out five buttons.

> Click the Launch button to run `CustomLayoutDemo` using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Previous page: How to Use SpringLayout
Next page: Doing Without a Layout Manager (Absolute Positioning)