Create Software Components 

Using Java Level 2

 

 

Course Info

Scheme

Resources

Tutorials

Java Demos

Utilities

Links


 

   Lecture 10

Layout Managers

How do you control the arrangement of components in Java so that your GUI looks as you wish it to look?  Read on for an explanation of three common layout managers.

Introduction

Creating and Setting Layout Managers

Creating a Layout Manager

Setting a Containers Layout

Quick Coding Example

FlowLayout

Creating a FlowLayout

BorderLayout

Creating a BorderLayout

GridLayout

Creating a GridLayout

Layouts and Containers within Containers


Introduction

Layout managers are used to arrange GUI components in a container.  It is possible to position components in a container using coordinates and absolute positioning but think how tedious that would be.  It is far easier to use the basic layout capabilities provided by layout managers.

Java comes with a few different layout managers.  We shall look at three commonly used layout managers:-

  • FlowLayout

Arranges components sequentially in rows in the order they were added to the container.  This is the default layout for panels

  • BorderLayout

Arranges components in regions - North, South, East, West and Center.  This is the default layout for applets

  • GridLayout

Places components in cells arranged into rows and columns.

You should note that the default layout manger for frames and applets is BorderLayout and the default for panels is FlowLayout.  However, you can set the layout manager for every container in your GUI as you choose.  Every container you have in your GUI can be set to have a different layout manager if desired. 

The applet below shows you the different layout managers in action.  Watch how the arrangement of the five buttons changes as you select a different layout manager from the menu.

~~~Applet~~~

There are two things you have to do to specify a layout for a container.

  1. Create an instance of a LayoutManager (using the new keyword)

  2. Set the layout of the container (using the setLayout method)

Let's get started.


Creating and Setting Layout Managers

Before examining each layout manager in detail, let's get a rough idea of how to create a layout manager instance and how to set a containers layout manager.  Then to get the feel of creating and setting layout manager objects we will finish this section with some practice coding.

 


Creating a Layout Manager

To create a layout manager object we use the new keyword and use a valid layout manager constructor :-

// creates an instance of a FlowLayout

FlowLayout myFlowLayout = new FlowLayout();

// creates an instance of a BorderLayout

BorderLayout myBorderLayout = new BorderLayout();

// creates an instance of a GridLayout

GridLayout myFlowLayout = new GridLayout(3,3);

That wasn't so bad was it.  I now have three different layout manager objects.  In each case, creating them is similar.  The GridLayout constructor is slightly different.  The 3,3 values placed in the parentheses indicate I want 3 rows and 3 columns, giving six cells for placing components.

 


Setting a Containers Layout

To set the layout manager of any container all you do is use the setLayout method and specify a layout manager object:-

// This is not real code

someContainer.setLayout(some layout manager object);

So there are two things we need to specify to use the setLayout method.  The container we wish to set the layout of and a layout manager object.

Well the first part is easy enough since we know about containers, but let's have a few examples:-

// This is still not real code

// sets the layout manager of a content pane

getContentPane().setLayout(some layout manager object);

// This is still not real code

// create a panel

JPanel myPanel = new JPanel();

// sets the layout manager of the panel

myPanel.setLayout (some layout manager object);

Let's specify a layout manager object now:-

// This is real code

// creates an instance of a FlowLayout

FlowLayout myFlowLayout = new FlowLayout();

// sets the layout manager of a content pane

getContentPane().setLayout(myFlowLayout);

I could use one line instead of two for creating and setting a layout:-

// creates and sets the layout manager of a content pane

getContentPane().setLayout( new FlowLayout() );

Notice how I created the new layout manager instance on the fly, inside the parentheses of the setLayout method.  Of course this means I haven't got a variable that references my layout manager object, so I cannot refer to it again later on in my code.

Now for a bit of coding practice:

 


Quick Coding Example

Let's play with some layout managers.  

This code creates an applet with five buttons, adds them to the content pane of an applet and sets the layout of the content pane to one of the created layout manager objects:- 

 

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

public class LayoutTest extends JApplet {

  public void init() {

      //create a variable that references 
     //the content pane of the applet
    Container appletContainer = getContentPane();

     // creates an instance of a FlowLayout
    FlowLayout myFlowLayout = new FlowLayout();

     // creates an instance of a BorderLayout
    BorderLayout myBorderLayout = new BorderLayout();

     // creates an instance of a GridLayout
    GridLayout myGridLayout = new GridLayout(3,3);

     // set the layout of the applet's content pane
    appletContainer.setLayout( myFlowLayout );

     // create some buttons
    JButton button1 = new JButton("Button1");
    JButton button2 = new JButton(" Button2");
    JButton button3 = new JButton(" Button3");
    JButton button4 = new JButton(" Button4");
    JButton button5 = new JButton(" Button5");

     // add the buttons to the applet
    appletContainer.add(button1);
    appletContainer.add(button2);
    appletContainer.add(button3);
    appletContainer.add(button4);
    appletContainer.add(button5);
  }
}

The layout could be set to one of three possible layouts since I created three different layout manager objects - myFlowLayout, myBorderLayout and myGridLayout.  The setLayout method above actually used the myFlowLayout object.  

What happens if you change the line of code:-

      appletContainer.setLayout( myFlowLayout );

to

      appletContainer.setLayout( myGridLayout );

or

      appletContainer.setLayout( myBorderLayout );

or you comment out the setLayout line

      // appletContainer.setLayout( myBorderLayout );

Some points to consider:-

  • The default layout manager for the content pane of an applet is BorderLayout.  So specifying myBorderLayout doesn't actually change anything.

  • We have seen before that adding more than one component to the content pane of an applet doesn't show more than one of the components (the last added to be exact).  We shall see why later.

  • What happens to the size and position of the components for each of the different layout managers when you resize the applet window?

The following sections look at each layout manager in more detail


FlowLayout   

FlowLayout arranges components in rows from left-to-right, top-to-bottom order. The order of the components will be the same order that you add them to the container.  

FlowLayout figures out how big the container is and positions of the components one by one along a row until the next component will not fit, in which case components are positioned on the next row, and so on.  If the container size is changed (e.g. when the user resizes the window), FlowLayout will recalculate new positions for all the components.  

FlowLayout places a component leaving it at the preferred size for that component (i.e. kind of a default size).

 


Creating a FlowLayout

There are three constructors to choose from when creating a FlowLayout object. 

  • FlowLayout ()

A FlowLayout manager object is created that will center-align components and space components 5 pixels apart.

  • FlowLayout (int align)

A FlowLayout manager object is created that will align components based on the alignment you specify (FlowLayout.LEFT, FlowLayout.CENTER, FlowLayout.RIGHT) and space components 5 pixels apart.

  • FlowLayout (int align, int hgap, int vgap)

A FlowLayout manager object is created that will align components based on the alignment you specify (FlowLayout.LEFT, FlowLayout.CENTER, FlowLayout.RIGHT) with the space between components specified by hgap and vgap

As you can see from the table, FlowLayout allows you to specify the alignment of the components if you choose the second or third constructor method.  You can have left, center and right-aligned.  By default, components are center-aligned.

To set the layout manager of a container all you do is use the setLayout method and specify a layout manager object you have created:-

FlowLayout aFlowLayout = new FlowLayout();

getContentPane().setLayout(aFlowLayout);

The first line creates a FlowLayout object referenced by aFlowLayout.  The second line sets the layout of the content pane of the applet to aFlowLayout.  Components added to this applets content pane would be arranged in rows, center-aligned and 5 pixels apart.

I could use one line of code instead of two for creating and setting a layout manager:-

getContentPane().setLayout(new FlowLayout());

All this means is that I cannot reference the FlowLayout object again since I created it on the fly inside the setLayout method

Let's try another example:-

FlowLayout anotherFlowLayout = new FlowLayout (FlowLayout.LEFT,10,20);

getContentPane().setLayout(anotherFlowLayout);

The first line creates a FlowLayout object referenced by anotherFlowLayout.  The second line sets the layout of the content pane of the applet to anotherFlowLayout.  Components added to this applets content pane would be arranged in rows, left-aligned and spaced 10 pixels apart horizontally, 20 pixels apart vertically.

I could use one line of code instead of two for creating and setting a layout manager:-

getContentPane().setLayout(new FlowLayout

                              (FlowLayout.LEFT,10,20));

Now try this code:-

 

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

public class LayoutFlow extends JApplet {

  public void init() {
     //create a variable that references 
     //the content pane of the applet

    Container appletContainer = getContentPane();

     // set the layout to FlowLayout
    appletContainer.setLayout( new FlowLayout() );

     // creates five buttons
    JButton button1 = new JButton("Button1");
    JButton button2 = new JButton(" Button2");
    JButton button3 = new JButton(" Button3");

     // add the buttons to the applet's content pane
    appletContainer.add(button1);
    appletContainer.add(button2);
    appletContainer.add(button3);
  }
}

 

You should end up with something that looks like this:-

~Try the activity~

Activity 10A

1. Use appletviewer to display your applet and resize the window until you are familiar with how FlowLayout arranges the buttons

2. As we can see, the default alignment of the components is center-alignment.  Amend the code above so that the alignment of the components is left or right.  Hint: check out the creation constructors.

 


BorderLayout   

BorderLayout divides a container into five different regions: North, South, East, West, and Center. The picture below shows five buttons, each one added to a different region.

You should note the following:-

  • The size of a component expands to fill the whole region.  This is why the buttons look an odd size.

  • Components in the North and South region are stretched horizontally.  

  • Components in the East and West region are stretched vertically. 

  • The center area expands horizontally and vertically as needed.   Try changing the size of an applet window set with a BorderLayout.  You'll see that only the center region expands. 

  • You can add at most one component to each region of a BorderLayout. To put more than one component in a region, put them in a panel (with its own layout), and then add that panel to a region. 

  • You can leave regions empty.  You don't have to add a component to every region.  Any region left without a component will have a zero size and the other regions will expand as necessary to fill the applet window.

  • The center region is excellent for placing components like text areas since the text area will expand with the region if the window is resized.


Creating a BorderLayout

There are two  constructors to choose from when creating a BorderLayout object. 

  • BorderLayout ()

A BorderLayout manager object is created.  There will be no spaces between the regions

  • BorderLayout (int hgap, int vgap)

A BorderLayout manager object is created, with the space between regions specified by hgap and vgap

To set the layout manager of a container all you do is use the setLayout method and specify a layout manager object you have created:-

BorderLayout aBorderLayout = new BorderLayout();

getContentPane().setLayout(aBorderLayout);

The first line creates a BorderLayout object referenced by aBorderLayout.  The second line sets the layout of the content pane of the applet to aBorderLayout.  

I could use one line of code instead of two for creating and setting a layout manager:-

getContentPane().setLayout(new BorderLayout());

All this means is that I cannot reference the BorderLayout object again since I created it on the fly inside the setLayout method.

Now what happens if I create, compile and run the following code?  You'll see that it is not quite right.

 

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

public class LayoutBorder extends JApplet {

    public void init() {

       //create a variable that references 

       //the content pane of the applet

       Container appletContainer = getContentPane();

 

      // set the layout to BorderLayout

      // the default for an applet is BorderLayout 

      //so this line is unnecessary really

       appletContainer.setLayout( new BorderLayout() );

 

      // creates five buttons
       JButton northButton = new JButton("North Button");
       JButton southButton = new JButton("South Button");
       JButton eastButton = new JButton("East Button");
       JButton westButton = new JButton("West Button");
       JButton centerButton = new JButton("Center Button");

 

      // add the buttons to the applet content pane
       appletContainer.add(northButton);
       appletContainer.add(southButton);
       appletContainer.add(eastButton);
       appletContainer.add(westButton);
       appletContainer.add(centerButton);
    }
}

Well, what's wrong?  Only the last button added to the applet's content pane appears.  

That's because, unlike a FlowLayout where the layout manager knows it has to place the components in rows, the BorderLayout manager has to be told which region to place a component in.  

By default, if you don't specify a region, the component will be added to the center region.  Moreover, since only one component is allowed per region, if you keep adding a component to the same region, it will just be placed over any existing components.

So how do we specify a region?  We use an alternative add method.  Instead of the familiar add method...

// This is not real code

// adds a component to a container

somecontainer.add(some component);

we use this...

// This is still not real code

// adds a component to a container in a specified region

somecontainer.add(some component, BorderLayout Region);

We specify a container to add the component to as normal. We also specify the component to add inside the parentheses as normal.  However, we now specify the BorderLayout region in which to place the component.  Regions can be specified using BorderLayout.NORTH, BorderLayout.EAST, BorderLayout.SOUTH, BorderLayout.WEST, or BorderLayout.CENTER.

Here are a few examples:-

// This is real code

// adds the button to the north region of the container 

appletContainer.add(northButton, BorderLayout.NORTH);

// adds the button to the south region of the container 

appletContainer.add(northButton, BorderLayout.SOUTH);

~Try the activity~

Activity 10B

1. Amend the LayoutBorder code above so that each button is placed in a different region of the applet container.  It should end up looking similar to the picture shown at the start of this section.

2. Use appletviewer to display your applet and resize the window until you are familiar with the expanding habits of each region.



GridLayout   

Look at the picture of buttons arranges in a GridLayout.  

As we can see, this layout manager takes a group of components and arranges them in cells, drawn all the same.  We just specify the number of rows and columns when we create the GridLayout instance. 

In the case above we have 3 rows, 3 columns making 6 cells.  One cell is empty because I only added five component to the container.

If you resize a GridLayout window the cells and contents resize to fit the new window.

 


Creating a GridLayout

There are two  constructors to choose from when creating a GridLayout object. 

  • GridLayout(int rows, int columns)

A GridLayout manager object is created with the specified number of rows and columns.  There will be no spaces between the cells

  • GridLayout(int rows, int columns, int hgap, int vgap)

A GridLayout manager object is created  with the specified number of rows and columns and the space between cells specified by hgap and vgap.

To set the layout manager of a container to a aGridLayout all you do is use the setLayout method and specify a layout manager object.  So:-

 

// create a GridLayout instance with 3 rows and 3 columns

GridLayout aGridLayout = new GridLayout(3,3);

// set the layout of the applet container to aGridLayout

getContentPane().setLayout(aGridLayout);

The first line creates a GridLayout object referenced by aGridLayout.  The second line sets the layout of the content pane of the applet to aGridLayout.  

I could use one line of code instead of two for creating and setting a layout manager:-

getContentPane().setLayout(new GridLayout(3,3));

All this means is that I cannot reference the GridLayout object again since I created it on the fly inside the setLayout method.

Now create, compile and run the following code:-

 

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

public class LayoutGrid extends JApplet {

    public void init() {

       //create a variable that references 

       //the content pane of the applet

       Container appletContainer = getContentPane();

 

      // set the layout to GridLayout 

       appletContainer.setLayout( new GridLayout(3,3) );

 

      // creates five buttons
       JButton button1 = new JButton("Button1");
       JButton button2 = new JButton("Button2");
       JButton button3 = new JButton("Button3");
       JButton button4 = new JButton("Button4");
       JButton button5 = new JButton("Button5");

 

      // add the buttons to the applet content pane
       appletContainer.add(button1);
       appletContainer.add(button2);
       appletContainer.add(button3);
       appletContainer.add(button4);
       appletContainer.add(button5);
    }
}

You should get something similar to the picture shown at the beginning of this section.

~Try the activity~

Activity 10C

1. Amend the LayoutGrid code above so that the horizontal space between cells is 10 pixels and the vertical space is 20 pixels. 

2. Change the text of one of the buttons to something like "This is a really long button caption" and see what happens to the size of the cells. 

3. What happens if you change the line:-

       appletContainer.setLayout( new GridLayout(3,3) );

to

       appletContainer.setLayout( new GridLayout(0,3) );

or

       appletContainer.setLayout( new GridLayout(3,0) );

 


 


Layouts and Containers within Containers

Have a look at the picture below.  Do you recall this applet from the JButton tutorial?  Which layout manager do you think I used?

Yes, I used a FlowLayout .  However, suppose none of the layout managers quite arranges our GUI in the way we want.  Examine the picture below.  Do you recall this applet from the JCheckBox tutorial?  How do you suppose I managed to arrange the components in this way?

None of the three layout managers would position the components in such a fashion.

It cannot be a BorderLayout because the Snow checkbox would expand to fill the region and cover the Cloud checkbox.  It cannot be a GridLayout because we don't have three equally sized cells.  It cannot be a FlowLayout because the two checkboxes are not arranged in a row.  

Here is a simplification of some of the code I used:-

    //set the applet's content pane to a flow layout

    getContentPane().setLayout(new FlowLayout());

 

    //create two panels

    JPanel aPane1 = new JPanel ();
    JPanel aPane2 = new JPanel ();

 

    //add the panels to the content pane

    //they will be added in a flow layout
    getContentPane().add( aPane1);
    getContentPane().add(aPane2);

 

    //change the layout of the panels to grid layout

    aPane1.setLayout(new GridLayout(2,1));
    aPane2.setLayout(new GridLayout(1,1));

    //add the checkboxes to the first panel

    //they will be added in a grid type of arrangement

    aPane1.add(cloudButton); 
    aPane1.add(snowButton); 

 

    //add the image label to the second panel

    aPane2.add(aLabel);

Yes, I created two panels and added them to the content pane of the applet, after changing the content pane from the default BorderLayout to FlowLayout.  This means that the panels are arranged in a row.  Then I added the components into the panels in a grid arrangement.  Try creating a similar sort of applet.  Don't forget, if you want spaces between components then you should choose the appropriate constructors for the layout managers.

What about the picture of the applet shown below?  Do you recall this applet from the JComboBox tutorial?  How did I manage this arrangement?  I have a JLabel at the top, a JComboBox just below and an image JLabel below this.

 

Perhaps it is a Flowlayout, where the applet window width is not too wide so the layout manager has to arrange the components in separate rows!  No - the image JLabel would be a smaller size (the exact size of the image).

Perhaps it is a GridLayout with three rows.   No - all the components would be resized in their cells so they were exactly the same size as each other.

I confess to using two panels again.  The content pane of the applet was left to its default BorderLayout and the first panel containing the JLabel and JComboBox were added to the North region.  The second panel containing the image JLabel was added to the Center region .

Finally, what about the applet shown in the picture below?  You will also find this in the JComboBox tutorial?  

I bet you think its a Flowlayout?  Only parts of it are in a Flowlayout.  The top label (the one with the 'Font Changer' caption) would not fit in with a Flowlayout would it?  The border around the four lower components separates them from the top label.  

I'm not going to tell you how I did it.  How would do it?


That is folks!!

Now try the Layout Managers exercise

 

  Site Home 

Java Home   

  Forum  

Course Info

Welcome

Overview

Assessment

Qualification

Scheme of Work

Assignments

Resources

Information

Blackboard

Learning Center

Web Materials

Reading

Java Demos

Utilities

Links

Lecture Materials

Tutorials & Notes

Exercises

Activities

Quizzes

 

Site Home

Top

Unit Home

ADR 2002