Layout managers give you the following advantages:
A Java UI container (java.awt.Container
) uses a special object called a layout manager to control how components are located and sized in the container each time it is displayed. A layout manager automatically arranges the components in a container according to a particular set of rules specific to that layout manager.
The layout manager sets the sizes and locations of the components based on various factors such as
constraints
associated with each component.
preferredSize, minimumSize, maximumSize, alignmentX,
alignmentY
.
In the Java AWT, certain types of containers use specific layout managers by default:
FlowLayout
.
BorderLayout
.
When you create a container in a Java program, you can accept the default layout manager for that container type, or you can override the default by specifying a different type of layout manager.
Normally, when coding your UI manually, you override the default layout manager before adding components to the container. When using the UI designer, you can change the layout whenever you like. JBuilder will adjust the code as needed.
JBuilder's UI designer uses a default layout manager for each container, usually the layout of the AWT parent container. If you want to use a different layout manager than the default one, you can do so by explicitly adding a layout manager to the source code for the container, or by selecting a layout from the container's layout
property list in the Inspector.
layout
properties for a <default> layout. If you want to modify the properties for a container's layout manager, you must specify an explicit layout manager, then its properties will be accessible in the Inspector.
XYLayout
is a feature of JBuilder Professional and Enterprise.
You choose a layout manager based on the overall design you want for the container. But, some layouts can be difficult to work with in the UI designer because they immediately take over placement and resizing of a component as soon as you drop it onto the container. To alleviate this problem while you're trying to prototype your UI in the designer, you can use null
layout or the JBuilder custom layout called XYLayout
which leaves the components exactly where you place them and lets you specify their size.
However, there are differences between the two:
XYLayout
knows about a component's preferredSize
, so if you choose the preferredSize
for the component (-1 value), XYLayout
adjusts the size of the component to match the look and feel of your system. You can't do this with null
layout.
null
clutters up your code with setBounds()
calls. XYLayout
doesn't.
Starting with null
or XYLayout
makes prototyping easier in your container. Later, after adding components to the container, you can switch to an appropriate portable layout for your design. We recommend never leaving a container in null
or XYLayout
for deployment.
Because these layouts use absolute positioning, components do not adjust well when you resize the parent containers. These layouts also do not adjust well to differences in users and systems, and therefore, are not portable layouts.
(See the topic called XYLayout for more information.)
In some designs, you might use nested panels to group components in the main Frame
, using various different layouts for the Frame
and each of its panels.
Experiment with different layouts to see their effect on the container's components. If you find the layout manager you've chosen doesn't give you the results you want, try a different one or try nesting multiple panels with different layouts to get the desired effect.
For a more detailed discussion of each layout, see the individual topics for each layout in "Layouts provided with JBuilder".
layout
property. The layout manager has properties that can affect the sizing and location of all components added to the container. These properties can be viewed and edited in the Inspector when the layout manager is selected in the component tree. The layout manager displays as an item in the tree just below the container to which it is attached.
constraints
object or produce a constraint value, which provides additional information about how the layout manager should size and locate this specific component. The type of constraint object or value created depends upon the type of layout manager being used. The Inspector displays the constraints of each component as if they were properties of the component itself, and it allows you to edit them.
BorderLayout
has properties called hgap
(horizontal gap) and vgap
(vertical gap) that determine the distance between components, while each component in the BorderLayout
container has a constraint value, called constraints
in the Inspector, with a possible value of NORTH, SOUTH, EAST, WEST, or CENTER.
FlowLayout
and GridLayout
have properties you can use to modify the alignment of components or the vertical and horizontal gap between them.
GridLayout
has properties for specifying the number of rows and columns.
GridBagLayout
has no properties itself. However, each component placed into a GridBagLayout
container has a constraints object associated with it that has many properties that control the component's location and appearance, such as
layout
property in the Inspector for containers. With a click of the mouse you can choose a new layout for any container in the UI designer.
To select a new layout,
layout
property.
layout
property's value field and choose a layout from the drop-down list.
setLayout
.
gridLayout1
for jPanel1
is selected.
GridLayout
, you can change the number of columns or rows in the grid and the horizontal and vertical gap between them.
The designer displays the changes immediately, and JBuilder modifies the source code's jbInit()
method.
constraint
property of that component in the Inspector. It also adds it to the source code as a parameter of the add()
method call in the jbInit()
method.
To edit a component's layout constraints,
constraints
property in the Inspector.
The methods for this look like property getters and represent the following.
getPreferredSize()
preferredSize
may or may not be considered in laying out the container.
getMinimumSize()
minimumSize
of a component may be limited, for example, by the size of a label. For most of the AWT controls, minimumSize
is the same as preferredSize
. Layout managers generally respect minimumSize
more than they do preferredSize
.
getMaximumSize()
minimumSize
. For instance, BorderLayout
could limit the center component's size to its maximum size and then either give the space to the edge components or limit the size of the outer window when resized.
getAlignmentX()
getAlignmentY()
To understand how each layout manager uses these pieces of information, study the individual layouts described in "Layouts provided with JBuilder".
java.awt.Window
(such as a Frame
or Dialog
), you can control its size and location at runtime. The size and location is determined by a combination of what the code does when the UI window is created and what the user does to resize or reposition it.
When the UI window is created and various components are added to it, each component added affects the preferredSize
of the overall window, typically making the preferredSize
of the window container larger as additional components are added. The exact effect this has on preferredSize
depends on the layout manager of the outer container, as well as any nested container layouts. For more details about the way that preferredLayoutSize
is calculated for various layouts, see the sections in this document on each type of layout.
The size of the UI window, as set by your program (before any additional resizing that may be done by the user), is determined by which container method is called last in the code:
pack()
setSize()
location
property of the container (for example by calling setLocation()
before making it visible).
pack()
method on a window, you are asking it to compute its preferredSize
based upon the components it contains, then size itself to that size. This generally has the effect of making it the smallest it can be while still respecting the preferredSize
of the components placed within it.
You can call the pack()
method to automatically set the window to a size that is as small as possible and still have all of the controls and subcontainers on it look good. Note that the Application.java
file created by the Application wizard calls pack()
on the frame it creates. This causes the frame to be packed to its preferredSize
before being made visible.
preferredSize
is calculated differently for containers with different layouts.
Portable layouts
Portable layouts, such as FlowLayout
and BorderLayout
, calculate their preferredSize
based on a combination of the layout rules and the preferredSize
of each component that was added to the container. If any of the components are themselves containers (such as a Panel
), then the preferredSize
of that Panel
is calculated according to its layout and components, the calculation recursing into as many layers of nested containers as necessary.
For more information about preferredSize
calculation for particular layouts, see the individual layout descriptions.
XYLayout
XYLayout
is a feature of JBuilder Professional and Enterprise.
For XYLayout
containers, the preferredSize
of the container is defined by the values specified in the width
and height
properties of the XYLayout
. For example, if you have the following lines of code in your container initialization,
xYLayoutN.setWidth(400); xYLayoutN.setHeight(300);
and if xYLayoutN
is the layout manager for the container,
then its preferredSize
will be 400 x 300 pixels.
If one of the nested panels in your UI has XYLayout
, then that panel's preferredSize
is determined by the layout's setWidth()
and setHeight()
calls, and that is the value used for the panel in computing the preferredSize
of the next outer container.
For example, in the default Application wizard application, the nested panel occupying the center of the frame's BorderLayout
is itself initially in XYLayout
and is set to size 400 x 300. This has a significant effect on the overall size of the frame when it is packed, because the nested panel report its preferredSize
to be 400x300. The overall frame will be that plus the sizes necessary to satisfy the other components around it in the BorderLayout
of the frame.
setSize()
on the container (rather than pack()
or subsequent to calling pack()
), then the size of the container will be set to a specific size in pixels. This basically has the same effect as the user manually sizing the container: it overrides the effect of pack()
and preferredSize
for the container and sets it to some new arbitrary size.
setSize()
, you must call validate()
to get the children laid out properly. (Note that pack()
calls validate()
).
pack()
and not explicitly setSize()
, or you should give careful thought to the pixel sizes of various screens and do some reasonable calculation of the size to set.
For example, you may decide that, rather than calling pack()
, you want to always have the UI show up at 75% of the width and height of the screen. To do this, you could add the following
lines of code to your application class, instead of the call to pack()
:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); frame.setSize(screenSize.width * 3 / 4, screenSize.height * 3 / 4);
XYLayout
containers to a portable layout after prototyping.
An example of this is the code that is generated by the Center Frame On Screen option of the Application wizard. This option creates additional code in the Application
class which, after creating the frame, positions it in the center of the screen. Take a look at the code generated by this option to see a good example of how to center your UI.
//Center the window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
pack()
, validate()
, setSize()
, or setLocation()
can be made from inside the UI container class, for example, this.pack()
. They can also be called from the class that creates the container (for example, frame.pack()
called after invoking the constructor, before the setVisible()
). The latter is what the Application wizard-generated code does: the calls to pack()
or validate()
and setLocation()
are placed in the Application
class, after the frame is constructed and the jbInit()
is therefore finished.
How should you decide where to put your calls for sizing and positioning your UI?
jbInit()
).
Application
class.
layout
property list, you need to register the layout assistant for it. There is a sample layout assistant in samples/OpenToolsAPI/layoutassistant
.
The registration step is a one-line call to the initOpentool()
static method. There you tell it which layout assistant should handle your layout. You can use the BasicLayoutAssistant
, or extend it depending upon how much functionality you need.
If the custom Layout Manager
uses a constraint class, additional integration can be performed by
supplying a class implementing java.beans.PropertyEditor
for editing the constraint.
This property editor would also need to be on the JBuilder classpath.
You would then need to extend BasicLayoutAssistant
and override two
methods:
public java.beans.PropertyEditor getPropertyEditor() { //return an instance of the constraints property editor return new com.mycompany.MyLayoutConstrainteditor(); } public String getContstraintsType () { // return the fully qualified constraint class name as a string, for example return "com.mycompany.myLayout"; }
BasicLayoutAssistant
is a skeletal implementation of the interface
com.borland.jbuilder.designer.ui.LayoutAssistant
.
Each LayoutManager
must be associated with a class that implements this
interface in order for the designer to be able to manipulate the layout. Layouts that do not have a layout assistant can still be used, but you cannot get BasicLayoutAssistant
assigned to them, and therefore, you cannot move components or convert a container layout to such a layout.
For further information on layout assistants see opentools/com.borland.jbuilder.designer.ui.LayoutAssistant.html
or look at the sample jbuilder/samples/OpenToolApi/LayoutAssistant/LayoutAssistant.jpr
.
JBuilder Professional and Enterprise also provide these custom layouts:
XYLayout
, which keeps components you put in a container at their original size and location (x,y coordinates)
PaneLayout
, used to control the percentage of the container each of its components occupies.
VerticalFlowLayout
, which is very similar to FlowLayout
except that it arranges the components vertically instead of horizontally
BoxLayout2
, a bean wrapper class for Swing's BoxLayout
, which allows it to be selected as a layout in the Inpsector
OverlayLayout2
, a bean wrapper class for Swing's OverlayLayout
, which allows it to be selected as a layout in the Inspector
Each of JBuilder's layout managers is explained in detail later in this section.
You can create custom layouts of your own, or experiment with other layouts such as the ones in the sun.awt
classes or third-party layout managers. Many of these are public domain on the Web. If you want to use a custom layout in the UI designer, you may have to provide a Java helper class file to help the UI designer use the layout.
Most UI designs will use a combination of layouts by nesting different layout panels within each other. To see how this is done, see "Using nested panels and layouts" and the tutorial "Creating a UI with nested layouts".