FormLayout is a powerful, flexible and precise general purpose
layout manager. It aligns components vertically and horizontally in
a dynamic rectangular grid of cells, with each component occupying one or
more cells.
A
whitepaper
about the FormLayout ships with the product documentation and is available
online.
To use
FormLayout
you first define the grid by specifying the
columns and rows. In a second step you add components to the grid. You can
specify columns and rows via human-readable String descriptions or via
arrays of
ColumnSpec
and
RowSpec
instances.
Each component managed by a FormLayout is associated with an instance of
CellConstraints
. The constraints object specifies where a component
should be located on the form's grid and how the component should be
positioned. In addition to its constraints object the
FormLayout
also considers each component's minimum and
preferred sizes in order to determine a component's size.
FormLayout has been designed to work with non-visual builders that help you
specify the layout and fill the grid. For example, the
ButtonBarBuilder
assists you in building button
bars; it creates a standardized FormLayout and provides a minimal API that
specializes in adding buttons. Other builders can create frequently used
panel design, for example a form that consists of rows of label-component
pairs.
FormLayout has been prepared to work with different types of sizes as
defined by the
Size
interface.
Example 1 (Plain FormLayout):
The following example creates a panel with 3 data columns and 3 data rows;
the columns and rows are specified before components are added
to the form.
FormLayout layout = new FormLayout(
"right:pref, 6dlu, 50dlu, 4dlu, default", // columns
"pref, 3dlu, pref, 3dlu, pref"); // rows
CellConstraints cc = new CellConstraints();
JPanel panel = new JPanel(layout);
panel.add(new JLabel("Label1"), cc.xy (1, 1));
panel.add(new JTextField(), cc.xywh(3, 1, 3, 1));
panel.add(new JLabel("Label2"), cc.xy (1, 3));
panel.add(new JTextField(), cc.xy (3, 3));
panel.add(new JLabel("Label3"), cc.xy (1, 5));
panel.add(new JTextField(), cc.xy (3, 5));
panel.add(new JButton("..."), cc.xy (5, 5));
return panel;
Example 2 (Using PanelBuilder):
This example creates the same panel as above using the
PanelBuilder
to add components to the form.
FormLayout layout = new FormLayout(
"right:pref, 6dlu, 50dlu, 4dlu, default", // columns
"pref, 3dlu, pref, 3dlu, pref"); // rows
PanelBuilder builder = new PanelBuilder(layout);
CellConstraints cc = new CellConstraints();
builder.addLabel("Label1", cc.xy (1, 1));
builder.add(new JTextField(), cc.xywh(3, 1, 3, 1));
builder.addLabel("Label2", cc.xy (1, 3));
builder.add(new JTextField(), cc.xy (3, 3));
builder.addLabel("Label3", cc.xy (1, 5));
builder.add(new JTextField(), cc.xy (3, 5));
builder.add(new JButton("..."), cc.xy (5, 5));
return builder.getPanel();
Example 3 (Using DefaultFormBuilder):
This example utilizes the
DefaultFormBuilder
that
ships with the source distribution.
FormLayout layout = new FormLayout(
"right:pref, 6dlu, 50dlu, 4dlu, default", // columns
""); // add rows dynamically
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.append("Label1", new JTextField(), 3);
builder.append("Label2", new JTextField());
builder.append("Label3", new JTextField());
builder.append(new JButton("..."));
return builder.getPanel();
addGroupedColumn
public void addGroupedColumn(int columnIndex)
Adds the specified column index to the last column group.
In case there are no groups, a new group will be created.
columnIndex
- the column index to be set grouped
addGroupedRow
public void addGroupedRow(int rowIndex)
Adds the specified row index to the last row group.
In case there are no groups, a new group will be created.
rowIndex
- the index of the row that should be grouped
addLayoutComponent
public void addLayoutComponent(Component comp,
Object constraints)
Adds the specified component to the layout, using the specified
constraints
object. Note that constraints are mutable and
are, therefore, cloned when cached.
comp
- the component to be addedconstraints
- the component's cell constraints
addLayoutComponent
public void addLayoutComponent(String name,
Component component)
Throws an UnsupportedOperationException
. Does not add
the specified component with the specified name to the layout.
name
- indicates entry's position and anchorcomponent
- component to add
appendColumn
public void appendColumn(ColumnSpec columnSpec)
Appends the given column specification to the right hand side of all
columns.
columnSpec
- the column specification to be added
appendRow
public void appendRow(RowSpec rowSpec)
Appends the given row specification to the bottom of all rows.
rowSpec
- the row specification to be added to the form layout
getColumnCount
public int getColumnCount()
Returns the number of columns in this layout.
getColumnGroups
public int[][] getColumnGroups()
Returns a deep copy of the column groups.
- the column groups as two-dimensional int array
getColumnSpec
public ColumnSpec getColumnSpec(int columnIndex)
Returns the ColumnSpec
at the specified column index.
columnIndex
- the column index of the requested ColumnSpec
- the
ColumnSpec
at the specified column
getConstraints
public CellConstraints getConstraints(Component component)
Looks up and returns the constraints for the specified component.
A copy of the actual CellConstraints
object is returned.
component
- the component to be queried
- the
CellConstraints
for the specified component
getLayoutAlignmentX
public float getLayoutAlignmentX(Container parent)
Returns the alignment along the x axis. This specifies how
the component would like to be aligned relative to other
components. The value should be a number between 0 and 1
where 0 represents alignment along the origin, 1 is aligned
the furthest away from the origin, 0.5 is centered, etc.
parent
- the parent container
- the value
0.5f
to indicate center alignment
getLayoutAlignmentY
public float getLayoutAlignmentY(Container parent)
Returns the alignment along the y axis. This specifies how
the component would like to be aligned relative to other
components. The value should be a number between 0 and 1
where 0 represents alignment along the origin, 1 is aligned
the furthest away from the origin, 0.5 is centered, etc.
parent
- the parent container
- the value
0.5f
to indicate center alignment
getLayoutInfo
public FormLayout.LayoutInfo getLayoutInfo(Container parent)
Computes and returns the horizontal and vertical grid origins.
Performs the same layout process as
#layoutContainer
but does not layout the components.
This method has been added only to make it easier to debug
the form layout.
You must not call this method directly;
It may be removed in a future release or the visibility
may be reduced.
parent
- the Container
to inspect
- an object that comprises the grid x and y origins
getRowCount
public int getRowCount()
Returns the number of rows in this layout.
getRowGroups
public int[][] getRowGroups()
Returns a deep copy of the row groups.
- the row groups as two-dimensional int array
getRowSpec
public RowSpec getRowSpec(int rowIndex)
Returns the RowSpec
at the specified row index.
rowIndex
- the row index of the requested RowSpec
- the
RowSpec
at the specified row
insertColumn
public void insertColumn(int columnIndex,
ColumnSpec columnSpec)
Inserts the specified column at the specified position. Shifts components
that intersect the new column to the right hand side and readjusts
column groups.
The component shift works as follows: components that were located on
the right hand side of the inserted column are shifted one column to
the right; component column span is increased by one if it intersects
the new column.
Column group indices that are greater or equal than the given column
index will be increased by one.
columnIndex
- index of the column to be insertedcolumnSpec
- specification of the column to be inserted
insertRow
public void insertRow(int rowIndex,
RowSpec rowSpec)
Inserts the specified column at the specified position. Shifts
components that intersect the new column to the right and readjusts
column groups.
The component shift works as follows: components that were located on
the right hand side of the inserted column are shifted one column to
the right; component column span is increased by one if it intersects
the new column.
Column group indices that are greater or equal than the given column
index will be increased by one.
rowIndex
- index of the row to be insertedrowSpec
- specification of the row to be inserted
invalidateLayout
public void invalidateLayout(Container target)
Invalidates the layout, indicating that if the layout manager
has cached information it should be discarded.
target
- the container that holds the layout to be invalidated
layoutContainer
public void layoutContainer(Container parent)
Lays out the specified container using this form layout. This method
reshapes components in the specified container in order to satisfy the
contraints of this
FormLayout
object.
Most applications do not call this method directly.
The form layout performs the following steps:
- find components that occupy exactly one column or row
- compute minimum widths and heights
- compute preferred widths and heights
- give cols and row equal size if they share a group
- compress default columns and rows if total is less than pref size
- give cols and row equal size if they share a group
- distribute free space
- set components bounds
parent
- the container in which to do the layout
Container
, Container.doLayout()
maximumLayoutSize
public Dimension maximumLayoutSize(Container target)
Returns the maximum dimensions for this layout given the components
in the specified target container.
target
- the container which needs to be laid out
- the maximum dimensions for this layout
minimumLayoutSize
public Dimension minimumLayoutSize(Container parent)
Determines the minimum size of the
parent
container
using this form layout.
Most applications do not call this method directly.
parent
- the container in which to do the layout
- the minimum size of the
parent
container
preferredLayoutSize
public Dimension preferredLayoutSize(Container parent)
Determines the preferred size of the
parent
container using this form layout.
Most applications do not call this method directly.
parent
- the container in which to do the layout
- the preferred size of the
parent
container
Container.getPreferredSize()
removeColumn
public void removeColumn(int columnIndex)
Removes the column with the given column index from the layout.
Components will be rearranged and column groups will be readjusted.
Therefore, the column must not contain components and must not be part
of a column group.
The component shift works as follows: components that were located on
the right hand side of the removed column are moved one column to the
left; component column span is decreased by one if it intersects the
removed column.
Column group indices that are greater than the column index will be
decreased by one.
Note: If one of the constraints mentioned above
is violated, this layout's state becomes illegal and it is unsafe
to work with this layout.
A typical layout implementation can ensure that these constraints are
not violated. However, in some cases you may need to check these
conditions before you invoke this method. The Forms extras contain
source code for class
FormLayoutUtils
that provides
the required test methods:
#columnContainsComponents(Container, int)
and
#isGroupedColumn(FormLayout, int)
.
columnIndex
- index of the column to remove
removeLayoutComponent
public void removeLayoutComponent(Component comp)
Removes the specified component from this layout.
Most applications do not call this method directly.
comp
- the component to be removed.
Container.remove(java.awt.Component)
, Container.removeAll()
removeRow
public void removeRow(int rowIndex)
Removes the row with the given row index from the layout. Components
will be rearranged and row groups will be readjusted. Therefore, the
row must not contain components and must not be part of a row group.
The component shift works as follows: components that were located
below the removed row are moved up one row; component row span is
decreased by one if it intersects the removed row.
Row group indices that are greater than the row index will be decreased
by one.
Note: If one of the constraints mentioned above
is violated, this layout's state becomes illegal and it is unsafe
to work with this layout.
A typical layout implementation can ensure that these constraints are
not violated. However, in some cases you may need to check these
conditions before you invoke this method. The Forms extras contain
source code for class
FormLayoutUtils
that provides
the required test methods:
#rowContainsComponents(Container, int)
and
#isGroupedRow(FormLayout, int)
.
rowIndex
- index of the row to remove
setColumnGroups
public void setColumnGroups(int[][] colGroupIndices)
Sets the column groups, where each column in a group gets the same
group wide width. Each group is described by an array of integers that
are interpreted as column indices. The parameter is an array of such
group descriptions.
Examples:
// Group columns 1, 3 and 4.
setColumnGroups(new int[][]{ {1, 3, 4}});
// Group columns 1, 3, 4, and group columns 7 and 9
setColumnGroups(new int[][]{ {1, 3, 4}, {7, 9}});
colGroupIndices
- a two-dimensional array of column groups indices
setColumnSpec
public void setColumnSpec(int columnIndex,
ColumnSpec columnSpec)
Sets the ColumnSpec
at the specified column index.
columnIndex
- the index of the column to be changedcolumnSpec
- the ColumnSpec
to be set
setConstraints
public void setConstraints(Component component,
CellConstraints constraints)
Sets the constraints for the specified component in this layout.
component
- the component to be modifiedconstraints
- the constraints to be applied
setRowGroups
public void setRowGroups(int[][] rowGroupIndices)
Sets the row groups, where each row in such a group gets the same group
wide height. Each group is described by an array of integers that are
interpreted as row indices. The parameter is an array of such group
descriptions.
Examples:
// Group rows 1 and 2.
setRowGroups(new int[][]{ {1, 2}});
// Group rows 1 and 2, and group rows 5, 7, and 9.
setRowGroups(new int[][]{ {1, 2}, {5, 7, 9}});
rowGroupIndices
- a two-dimensional array of row group indices.
setRowSpec
public void setRowSpec(int rowIndex,
RowSpec rowSpec)
Sets the RowSpec
at the specified row index.
rowIndex
- the index of the row to be changedrowSpec
- the RowSpec
to be set