Você está na página 1de 13

Layouts in java

FlowLayout
java.awt.FlowLayout arranges components from left-to-right and top-to-bottom, centering
components horizontally with a five pixel gap between them. When a container size is changed
(eg, when a window is resized), FlowLayout recomputes new positions for all components
subject to these constraints.
Use FlowLayout because it's quick and easy. It's a good first choice when using iterative
development. I often start with a FlowLayout in an early iteration then switch to a better layout,
if necessary, on a later iteration.
Example

The window above is the default size after packing the FlowLayout.
The window on the right shows the same window after it has been
resized by dragging the lower-right corner, resulting in components
flowing down onto other lines.

Source code for example
Here is the relevant part of the source code for the above example.
// Note: a real program would add listeners to the buttons.
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new JButton("Button 1"));
content.add(new JButton("2"));
content.add(new JButton("This is button three"));
content.add(new JButton("four"));
Constructors
Typically the constructor is called in the call to the container's setLayout method (see example
code). The parameterless FlowLayout() constructor is probably most common, but there are
some good places to use the alignment.
new FlowLayout() // default is centered with 5 pixel gaps
new FlowLayout(int align)
new FlowLayout(int align, int hgap, int vgap)
Alignment
align is one of FlowLayout.LEFT, FlowLayout.CENTER (the default), or FlowLayout.RIGHT.
You might want to use the RIGHT aligment when building a dialog that puts the OK and Cancel
buttons at the lower right.
Spacing
The default spacing is good for most purposes and is rarely changed. hgap is the size in pixels of
the horizontal gap (distance) between components, and vgap is the vertical gap.
Typical uses
Quick implementation. This is the most common use of FlowLayout. You can get
something working quickly, and change it, if necessary, in a later iteration.
Space around component in a BorderLayout. As a subpanel to keep components from
expanding. For example, you might want to add a button to the SOUTH part of a
BorderLayout, but don't want it to expand to the edges of the SOUTH region. Just put the
button in a FlowLayout JPanel and add that to the SOUTH.
Multiple components in a BorderLayout region. When you want to add several
components to a BorderLayout region, drop them into a FlowLayout panel and put that in
the BorderLayout.
Problem
FlowLayout makes components as small as possible, and does not use their preferred size. This
can show up when you define a JPanel for drawing. Typically you will set a preferred size, but
the panel may "disappear" in a FlowLayout because it was set to its minimum size (0).
BorderLayout
java.awt.BorderLayout divides a container (eg, JPanel) into 5 geographical sections: North,
South, East, West, and Center. This is a very commonly used layout.
Expand to fill region. Components start at their preferred size, but are expanded as needed to
fill the region they are in.
Use subpanel for more than one component in a region. You can add at most one component
to each region of a BorderLayout. To put more than one component in a section, put them in a
JPanel (with its own layout), then add that panel to the border layout.
Where extra space goes. The size of a region is adjusted depending on what is in it. If there is
nothing in an region, its size will be reduced to zero. Components in the North and South cells
are stretched horizontally, and those in East and West are stretched vertically to fill all the space.
The center is stretched vertically and horizontally as needed, so it is a good place to put graphics
or text areas that you want to expand.
Specifying the region. When you add components to a container which uses BorderLayout,
specify the target region as the second parameter as, for example, BorderLayout.NORTH.
Resizing

The window on the left
was created by the
sample code below. This
same window was made
larger by dragging on the
lower right corner. Note
which components had
horizontal space added to
them and which had
vertical space added to
them.

To prevent component resizing, add a component to a JPanel with FlowLayout, and then add that
panel to the BorderLayout. This is a common way to prevent resizing. The FlowLayout panel
will stretch, but the component in it will not.
Not all regions are required
If nothing has been added to a region, the neighboring
regions expand to fill that space.
This window was created with 5 pixel gaps using only the
NORTH, WEST, and CENTER regions. It was then resized,
which added both vertical and horizontal space to the
regions.

Constructors
If you don't need any space between regions, use the default constructor. You can also specify
the number of pixels between regions.
p.setLayout(new BorderLayout()); // Default is no gaps
p.setLayout(new BorderLayout(hgap, vgap);
Where hgap and vgap are the distances in pixels between the regions.
Example of Borderlayout with all regions filled
// File : layouts/borderLayout/BorderTest.java
// Purpose: Demo use of BorderLayout.
// Author : Fred Swartz - 2006-09-24 - Placed in public domain.

import java.awt.*;
import javax.swing.*;

///////////////////////////////////////////////// class BorderTest
class BorderTest extends JFrame {

//======================================================= main
public static void main(String[] args) {
JFrame window = new BorderTest();
window.setVisible(true);
}

//================================================ constructor
BorderTest() {
//... Create components (but without listeners)
JButton north = new JButton("North");
JButton east = new JButton("East");
JButton south = new JButton("South");
JButton west = new JButton("West");
JButton center = new JButton("Center");

//... Create content pane, set layout, add components
JPanel content = new JPanel();
content.setLayout(new BorderLayout());

content.add(north , BorderLayout.NORTH);
content.add(east , BorderLayout.EAST);
content.add(south , BorderLayout.SOUTH);
content.add(west , BorderLayout.WEST);
content.add(center, BorderLayout.CENTER);

//... Set window characteristics.
setContentPane(content);
setTitle("BorderTest");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
}




BoxLayout and Boxes
BoxLayout arranges components either horizontally or vertically in a
panel. You can control alignment and spacing of the components.
Complicated layouts can be made by combining many panels, some with
horizontal layout and some with vertical layouts.
Several classes are typically used:
javax.swing.BoxLayout, javax.swing.Box, and javax.swing.Box.Filler.
To Create a JPanel with BoxLayout
Choose either a horizontal layout (BoxLayout.X_AXIS) or vertical layout (BoxLayout.Y_AXIS)
for a JPanel.
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.add(some_component);
Unlike other layouts, the panel/container must be passed to the BoxLayout constructor.
Example
The above examples were created with this code, using either X_AXIS or Y_AXIS.
content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));
content.add(new JButton("Button 1"));
content.add(new JButton("2"));
content.add(new JButton("This is button three"));
The Box class
The Box class was designed to be a simple, and slightly more efficient, substitute for a JPanel
with a BoxLayout. Because it doesn't support everything that JPanel does (eg, borders), I
recommend using a JPanel with a BoxLayout rather than Box. However, the Box class has a
number of necessary methods for working with BoxLayouts.
Because Box is a Container with BoxLayout, all discussions of spacing and alignment apply
equally well to both JPanels with BoxLayouts and Boxes.
Creating Boxes
You can create the two kinds of boxes with:
import javax.swing.*;
. . .
Box vb = Box.createVerticalBox();
Box hb = Box.createHorizontalBox();
No Borders on Boxes
Boxes are lighter weight (ie, more efficient) than JPanel, but they don't support Borders. If you
need borders, either use a JPanel with BoxLayout, or put the Box into a JPanel with a border.
java.awt.GridBagLayout
Description
GridBagLayout lays out components based on a grid with rows and columns that need not all be
the same size. If you're familiar with HTML tables, you'll feel comfortable with the idea.
Unfortunately, GridBagLayout is infernally awkward and error-prone to use. After reading some
of this you might want to see example code at Example: GridBagLayout.
Abandon hope, all ye who use GridBagLayout
Altho GridBagLayout can produce acceptable results, it's not a happy story.
It is very difficult to work with because eleven constraint values are used for each
component! These constraint values are bundled in a java.awt.GridBagConstraints
object. Fortunately, most of them have reasonable defaults.
The layout doesn't have features which specifically help to use Sun's (or anyone else's)
Human Interface Guidelines, for example in handling gaps.
Spacing is specified in pixels, which provides no flexibility for screen resolution and font
changes.
I like this quote from Otaku, Cedric's blog: "GridBagLayout is an absolute disaster and
the perfect example of something that is completely flawed and violates with a stunning
regularity the principle of least surprise."
Everyone who has touched GridBagLayout will enjoy Totally Gridbag, little bit of Flash
foolishness - madbean.com/blog/2004/17/totallygridbag.html
Some prefer to call it "GridBugLayout".
Subpanels for unrelated components. An entire window may require use of nested panels --
don't try to force everything into one giant GridBagLayout. If some groups of components (eg,
radio buttons, groups of buttons, checkboxes) are unrelated to alignment with other components,
put them in their own panel and use an appropriate layout (often GridLayout).
Unequal rows and columns
The underlying idea is rows and columns, similar to HTML tables.
Rows and columns don't all have to be same size. The size of each row and column is
adjusted depending on maximum component size in the row/column and their constraints.
A component display area may span several rows and/or columns. Describe this area by
giving the row, column, width (in columns), and height (in rows).
A components doesn't have to fill its display area; constraints describe how to align it
within its area.
Three categories of constraint parameters
GridBagLayout performs three functions using values from the GridBagConstraints parameter in
the add() method. The names [note the case violations of the standard Java naming convention]
are the following.
1. Grid position, width and height describe the display area.. gridx, gridy, gridwidth, and
gridheight.
2. Position within the display area. fill, anchor, insets, ipadx, and ipady.
3. Identifying rows and columns which receive extra space on expansion. weightx, and
weighty.
Constructor
JPanel p = new JPanel(new GridBagLayout());
or
JPanel p = new JPanel();
p.setLayout(new GridBagLayout());
Do not give the number of rows and columns when you create a new GridBagLayout. The are
computed by the layout manager as a consequence of what you add.
Adding a component
Components are added to JPanel p like this:
p.add(component, constraintObj);
Constraint parameters are instance fields in a GridBagConstraints object. The add() method
clones (copies) the constraint object, so typically the same GridBagConstraints object is reused
to pass constraints for the next component. It is common to use only one GridBagConstraints
object to add all components, changing fields as necessary between adds, but this practice also
leads to many errors and code which is difficult to change.
GridBagConstraints fields
The fields can divided into three groups:
Necessary - row and column coordinates, width and height in terms of rows and columns
Describe the location and size (in rows and columns) of the component using gridx,
gridy, gridwidth, and gridheight.
Common - expandability and alignment
If a column or row can use extra space when a window is expanded, set weightx and
weighty to 1.0; you will rarely want to use other values.
Use fill depending on what the type of component is. For example, a JTextField can
usually grow horizontally, so you would use
gbc.fill = GridBagConstraints.HORIZONTAL;
to allow it to stretch.
Use anchor to tell which edges of the display area a component should be attached to.
Less common - surrounding spacing
You can also control the space around a component with ipadx and ipady.
To control the amount of unused space around a component, use insets.
GridBagConstraints attribute summary
gridx
gridy
The int column (gridx) and row (gridy) of the component. If requires more than
one cell (gridwidth or gridheight > 1), this is the coordinate of the top-left cell.
The row and columns start at zero. The value GridBagConstraints.RELATIVE
places the component in the next position.
gridwidth
gridheight
Number of columns or rows the component occupies.
GridBagConstraints.REMAINDER indicates that this component should fill out all
rows or columns to the end. Default 1. Note these names violates naming standards
(second word not capitalized).
weightx
weighty
These double variables (default value 0) are used in calculating where space is
allocated in rows and columns when a window is resized. extra space should be
allocated in a column horizontally (weightx) and row vertically (weighty).
A column width is originally calculated as the maximum width of the preferred
sizes of the components in that column. If a component is narrower than the column
width, the value of the fill attribute is used in deciding how to use that extra space
(see below).
Extra horizontal space is allocated to a column in proportion to the maximum
weightx value for that column. If weightx is zero, no extra space is allocated.
Because these weights are relative, you can assign any arbitrary positive double
value to produce the desired layout, altho it is common to work in the range 0-1.
The analogous procedure is performed for the row heights using weighty.
fill
Fill specifies how the component should expand within its display area if the area
width/height is larger than its preferred size.
GridBagConstraints.NONE // Can't expand (Default)
GridBagConstraints.VERTICAL // Expand vertically
GridBagConstraints.HORIZONTAL // Expand horizontally
GridBagConstraints.BOTH // Expand vertically and
horizontally
For example, a text field typically expands horizontally
(GridBagConstraints.HORIZONTAL), a text area expands vertically and
horizontally (GridBagConstraints.BOTH), and a button might not expand at all
(GridBagConstraints.NONE). If a component isn't expanded to fill the space, the
anchor attribute (see below) is used to specify where it goes within that cell.
Default value GridBagConstraints.NONE.
anchor
If the component doesn't occupy its entire display area, anchor specifies where it
should be placed. The location is usually given as a compass direction. (A relative
system which works for both right-to-left and left-to-right languages is also
available).
GridBagConstraints.CENTER (the default),
GridBagConstraints.NORTH GridBagConstraints.SOUTH
GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHWEST
GridBagConstraints.EAST GridBagConstraints.WEST
GridBagConstraints.SOUTHEAST GridBagConstraints.NORTHWEST
insets
A java.awt.Insets object adds padding space to the component. Insets should be
rarely used because they often produce bad results, with the exception of JPanels
and JLabels. The constructor parameters (in pixels) specify the top, left, bottom,
right. For example,
gbc.insets = new Insets(10, 5, 10, 4);
Default value: Insets(0,0,0,0).
ipadx
ipady
These int fields specify an increase or decrease in the horizontal and/or vertical
preferred size of the component. Default value 0. Negative values can be used to
tighten the spacing. These values are rarely useful, altho they can be used for fine-
tuning spacing.
Java Idiom
It's common to write a utility method which sets the fields of a GridBagConstraints object. For
example,
GridBagConstraints gbc = new GridBagConstraints();
. . .
private void set_gbc(int row, int column, int width, int height, int fill) {
gbc.gridy = row;
gbc.gridx = column;
gbc.gridwidth = width;
gbc.gridheight = height;
gbc.fill = fill; // GridBagConstraints.NONE .HORIZONTAL .VERTICAL .BOTH
// leave other fields (eg, anchor) unchanged.
}
. . .
set_gbc(3, 2, 2, 1, GridBagConstraints.HORIZONTAL);
gbc.insets = new Insets(3,3,3,3); // put spacing around this field.
p.add(myTextField, gbc);
Adding a component
To add myField to the third row (2) and first column (0), where the button will be one grid cell
wide and one high, and it will be able to expand horizontally, do this:
set_gbc(2, 0, 1, 1, GridBagConstraints.HORIZONTAL);
gridbag.setConstraints(myField, gbc);
panel.add(myField);


GridLayout
GridLayout lays out
components in a rectangular
grid, where all cells are equal
size.

GridLayout forces components
to have the same size.
JPanel content = new JPanel(new GridLayout(2,2));
content.add(new JButton("Button 1"));
content.add(new JButton("2"));
content.add(new JLabel("")); // for empty cell
content.add(new JButton("This is button three"));
To Create a GridLayout
There are three constructors:
p.setLayout(new GridLayout()); // One row. Columns expand.
p.setLayout(new GridLayout(rows, cols));
p.setLayout(new GridLayout(rows, cols, hgap, vgap));
with the following int parameters: rows is number of rows, cols is number of columns, hgap is horizontal
space between components (in pixels), and vgap is vertical space between components (in pixels).

For example, this creates a panel with a grid layout of 4 rows and 3 columns. There are 5 pixels of
horizontal space between components and 10 pixels of space between vertical components.
JPanel p = new JPanel();
p.setLayout(new GridLayout(4, 3, 5, 10));
p.add(. . .);
To add Components to a GridLayout
Use the .add(. . .) method to add components to a container with a GridLayout. You do not (can
not) use the row and column to tell where to add the components -- add them in starting at the top left
and going across the row first.
Empty Cells
There is no way to leave a cell empty in a grid layout. Although it often works ok to leave the final cells
empty, there are reports of problems, so you should fill out the last cells in the final row too. The easiest
way to do this is to put an empty label in any cell you want to skip. Eg,
p.add(new JLabel(""));


Null Layout is Evil
You can set the layout manager to null(cont.setLayout(null);), but this is generally bad
practice.
Example - Compare constructors for the Km to Miles
example

You can see the complete FlowLayout version of this program at Example - Kilometers to Miles
- Complete. Below is a comparison of the layout section of the FlowLayout constructor with the
equivalent null layout constructor.
FlowLayout Null Layout
//... Content panel, layout, add
components
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new
JLabel("Kilometers"));
content.add(m_kilometersTf);
content.add(m_convertBtn);
content.add(new JLabel("Miles"));
content.add(m_milesTf);
this.setContentPane(content);
this.pack();
//... Create labels.
JLabel kmLabel = new
JLabel("Kilometers");//Note 1
JLabel miLabel = new JLabel("Miles");

//... Set the positions of components.
kmLabel.setBounds(5, 10, 62, 16);
//Note 2
m_kilometersTf.setBounds(72, 8, 114,
20);
m_convertBtn.setBounds(191, 5, 78, 26);
miLabel.setBounds(274, 10, 30, 16);
m_milesTf.setBounds(309, 8, 114, 20);

//... Content panel, layout, add
components
JPanel content = new JPanel();
content.setLayout(null);
//Note 3
content.add(kmLabel);
content.add(m_kilometersTf);
content.add(m_convertBtn);
content.add(miLabel);
content.add(m_milesTf);
this.setContentPane(content);
this.setSize(436, 63);
//Note 4
Notes
Note 1: Labels must be in variables to set their
bounds.
Note 2: How will you compute these coordinates?
Note 3: Set the layout manager to null.
Note 4: Explicitly set the size of the window.
Problems with null layout that regular layouts don't have
Difficult to change, therefore hard (expensive) to maintain
Moving, adding, removing, etc require a lot of recalculation. Relatively little work is required
with regular layouts.
Hard to get right in the first place
Exactly how do you get these coordinates?
System dependent
The components have different sizes in different systems. I once wrote a Java program that I
proudly showed to an important colleague, who unfortunately was using a different system. The
layout looked really, really bad - gaps, overlaps. What happened? Null layout! It was one of my
early programs and the last null layout I ever wrote.
Java version dependent
A little know fact is that between Java versions the rendering of components something changes
slightly. It's not big, but if you have things carefully aligned in null layouts, they may not be in
the next version of Java.
User setting dependent
Another little used feature is that the user can actually change Java's default settings for fonts
etc. I once decided I wanted larger fonts on the high resolution screen I had. Of course, this
completely breaks any null layouts altho regular layouts will adjust properly.
Not resizeable
It's not uncommon to have text fields/areas that the use might want to make larger by dragging
the lower right corner of the window. Impossible with null layouts, automatic with regular
layouts.

Você também pode gostar