This chapter shows you how to use the layout managers provided by the Lightweight UI Toolkit library. It also gives an example of writing a custom layout manager. For each layout manager, this chapter supplies sample code demonstrating how to use the layout manager and a general illustration.
In Lightweight UI Toolkit you can find the following layout managers:
A BorderLayout object has five areas. These areas are specified by the BorderLayout constants:
Center
East
North
South
West
When adding a component to a container, specify the component's location (for example, BorderLayout.CENTER
) as one of the arguments to the addComponent method. If this component is missing from a container, controlled by a BorderLayout object, make sure that the component's location was specified and that no other component was placed in the same location.
addComponent(BorderLayout.CENTER, component) // preferred
or
addComponent(“Center”, component) // valid but error prone
The center area gets as much of the available space as possible. The other areas expand only as much as necessary to fit the components that have been added to it. Often a container uses only one or two of the areas of the BorderLayout object — just the center, or the center and the bottom.
The BoxLayout class puts components either on top of each other or in a row – your choice.
To lay out components in a row, use BoxLayout.X_AXIS
as the axis indication.
BoxLayout boxLayout = new BoxLayout(BoxLayout.X_AXIS);
In this layout, the box layout manager honors the component width of each layout component to fill the width of the container, and the height is determined by the container height. Any extra space appears at the right side of the container, as shown in Figure 6-2.
Figure 6-2 BoxLayout.X_AXIS Components in a Row
To lay out components in a column, use BoxLayout.Y_AXIS
as the axis indication.
BoxLayout boxLayout = new BoxLayout(BoxLayout.Y_AXIS);
In this layout, the box layout manager honors the component height of each layout component to fill the height of the container, and the width is determined by the container width. Any extra space appears at the bottom of the container, as shown in Figure 6-3.
Figure 6-3 BoxLayout_Y_Axis Components in a Row
The FlowLayout class provides a very simple layout manager that is the default layout manager for Container objects.
The FlowLayout class puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows. To align the row to the left, right, or center, use a FlowLayout constructor that takes an alignment argument.
The code snippet below creates a FlowLayout object and the components it manages.
FlowLayout exampleLayout = new FlowLayout(); ... container.setLayout(exampleLayout); container.addComponent(new Button("Button 1")); container.addComponent(new Button("Button 2")); container.addComponent(new Button("Button 3")); container.addComponent(new Button("Button 4"));
When constructing a FlowLayout manager you can select either the Left, Right, or Center option to set up the component's orientation. The default alignment is Left. The following code snippet applies the Right component orientation to the above exampleLayout.
FlowLayout exampleLayout = new FlowLayout(Component.RIGHT);
Figure 6-5 FlowLayout With Right Alignment
A GridLayout object places components in a grid of cells. Each component takes all the available space within its cell, and each cell is exactly the same size.
The code snippet below creates the GridLayout object and the components it manages.
GridLayout exampleLayout = new GridLayout(0,2); ... container.setLayout(exampleLayout); container.addComponent(new Button("Button 1")); container.addComponent(new Button("Button 2")); container.addComponent(new Button("Button 3")); container.addComponent(new Button("Button 4"));
In this example the constructor of the GridLayout class creates an instance that has two columns and as many rows as necessary.
GroupLayout is a layout manager that was developed for GUI builders such as Matisse, the Java SE GUI builder delivered with the NetBeans IDE. Although the layout manager was originally designed to suit GUI builder needs, it also works well for manual coding. To get more information you can refer to the GroupLayout API (http://java.sun.com/javase/6/docs/api/javax/swing/GroupLayout.html (http://java.sun.com/javase/6/docs/api/javax/swing/GroupLayout.html
)) or review the Swing GroupLayout tutorial at:
http://java.sun.com/docs/books/tutorial/uiswing/layout/group.html (http://java.sun.com/docs/books/tutorial/uiswing/layout/group.html
)
Unlike other layout managers coordinate layout assigns a component an absolute position in relation to the space available within the UI. The coordinate layout allows developers to position components within an X/Y location, however, it doesn't guarantee the position won't change and doesn't determine absolute positions.
Instead coordinate layout accepts positions as "relative" and calculates the actual position based on available space. This is essential since the available size for a container might change at runtime based on font size, screen rotation, etcetera.
For example, a coordinate layout for 200x200 will show a 20x20 component placed in the 90x90 position exactly in the center, regardless of the actual size of the container. If the container is laid out to a larger size, for example, 190x300 the component in the center would still be centered.
Unlike the other standard layouts in LWUIT the coordinate layout allows positioning components on top of one another to achieve z-ordering. The z-ordering is determined by the order in which the components are placed into the parent container.The last component added is the one on top.
Display.init(this); final Form mainForm = new Form("Coordinate Layout"); mainForm.setLayout(new CoordinateLayout(200, 200)); Label centeredLabel = new Label("Center"); centeredLabel.setX(90); centeredLabel.setY(90); centeredLabel.getUnselectedStyle().setBgTransparency(100); centeredLabel.getUnselectedStyle().setBgColor(0xff); Label underCenter = new Label("Under Center"); underCenter.setX(80); underCenter.setY(95); Label top = new Label("Top Left"); top.setAlignment(Component.CENTER); top.setX(0); top.setY(0); top.setPreferredW(200); top.setPreferredH(30); top.getUnselectedStyle().setBgColor(0xff0000); mainForm.addComponent(underCenter); mainForm.addComponent(centeredLabel); mainForm.addComponent(top); mainForm.show();
This code produces Figure 6-7:
There are several interesting things we can glean even from this simple example:
Coordinate layout must be hard-coded. The coordinates are implicitly scaled by LWUIT so there is no need to use logic, such as getWidth/Height,
to calculate positions.
Elements are sized based on their preferred size, yet positioned based on their X and Y coordinates. Their dimensions determined via setWidth
and getHeight
are ignored.
Unlike the X and Y coordinates that are relative to layout dimensions, the preferred size is absolute in pixels and should be calculated based on content dimensions. This works as expected as long as you don't change the preferred size on your own.
Alignment and other LWUIT related positioning logic should work as you would expect.
The table layout is a part of the table component discussed later, however it is quite useful on its own. It is largely inspired by the HTML table tag and also influenced by AWT's GridBagLayout.
The table layout is a constraint based layout (similar to the border layout). Other layout managers expect components to be added on their own. For example:
container.addComponent(component);
The table layout container expects something like this:
container.addComponent(tableConstraint, component);
Notice that this syntax is optional. If the constraint is omitted, the component is placed in the next available cell.
The table layout will automatically size components to the largest preferred size in the row or column until you run out of space. If the table is not horizontally scrollable this happens when the edge of the parent container is reached (near the edge of the screen), and additional components are "crammed together". Notice that all cells in the table layout are always sized to fit the entire cell. To change a cell's alignment or margin, use the Component or Style methods.
The constraint argument is an instance of TableLayout.Constraint that can be used only once. Reusing the instance will cause an exception.
A constraint can specify the absolute row/column where the entry should fit as well as spanning between cell boundaries.
In Figure 6-8, the "First" cell is spanned vertically while the "Spanning" cell is spanned horizontally. This is immensely useful in creating elaborate UIs.
Constraints can also specify a height/width for a column/row that will override the default. This size is indicated in percentage of the total table layout size. In the code below you can see that the "First" label is sized to 50% width while the "Fourth" label is sized to 20% height.
final Form mainForm = new Form("Table Layout"); TableLayout layout = new TableLayout(4, 3); mainForm.setLayout(layout); TableLayout.Constraint constraint = layout.createConstraint(); constraint.setVerticalSpan(2); constraint.setWidthPercentage(50); mainForm.addComponent(constraint, new Label("First")); mainForm.addComponent(new Label("Second")); mainForm.addComponent(new Label("Third")); constraint = layout.createConstraint(); constraint.setHeightPercentage(20); mainForm.addComponent(constraint, new Label("Fourth")); mainForm.addComponent(new Label("Fifth")); constraint = layout.createConstraint(); constraint.setHorizontalSpan(3); Label span = new Label("Spanning"); span.getStyle().setBorder(Border.createLineBorder(2)); span.setAlignment(Component.CENTER); mainForm.addComponent(constraint, span); mainForm.show();