Containers and simple layout managers

 

The Container class

Object 

\

Component   

\

Container

Class

Description

Panel

The simplest container. Provides space in which an application can attach any other component, including other panels.

ScrollPane

A container which implements automatic horizontal and/or vertical scrolling

Window

A container for a top-level window that has no borders and no menu bar. Useful subclasses are Dialog and Frame.

Method

Usage

add()

Adds a component to the internal list

remove()

Removes a component from the internal list

removeAll()

Removes all components from the internal list

setLayout()

Sets the layout manager for the container

validate()

Causes the container to lay out its components again after a component has been added or removed

Notes:

  1. Many methods are overloaded to accept a range of parameter types and values

  2. As an extension of Component (and Object), all features of those classes are inherited

 

Layout managers

 

BorderLayout

North

West

 

 

Center

 

 

East

South

Example:

import java.awt.*;
import java.awt.event.*;

public class App extends Frame implements WindowListener, ActionListener {

  Button b1, b2, b3, b4, b5;

  public static void main(String[] args) {
    App myWindow = new App("Border Layout");
    myWindow.setSize(250,150);
    myWindow.setVisible(true);
  }

  public App(String title) {
    super(title);
    setLayout(new BorderLayout());
    addWindowListener(this);
    b1 = new Button("North");
    add(b1, BorderLayout.NORTH);
    b1.addActionListener(this);
    b2 = new Button("West");
    add(b2, BorderLayout.WEST);
    b2.addActionListener(this);
    b3 = new Button("Center");
    add(b3, BorderLayout.CENTER);
    b3.addActionListener(this);
    b4 = new Button("East");
    add(b4, BorderLayout.EAST);
    b4.addActionListener(this);
    b5 = new Button("South");
    add(b5, BorderLayout.SOUTH);
    b5.addActionListener(this);
  }

  public void actionPerformed(ActionEvent e) {
    remove((Component)e.getSource());
    validate();
  }

  public void windowClosing(WindowEvent e) {
    dispose();
    System.exit(0);
  }

  public void windowOpened(WindowEvent e) {}
  public void windowActivated(WindowEvent e) {}
  public void windowIconified(WindowEvent e) {}
  public void windowDeiconified(WindowEvent e) {}
  public void windowDeactivated(WindowEvent e) {}
  public void windowClosed(WindowEvent e) {}
}

Notes:

  1. The sample declares five Button object references (b1 through b5)

  2. In the constructor, setLayout() is explicitly coded but isn't really needed as BorderLayout is the default for a Frame

  3. With BorderLayout, the add() method accepts a second parameter that specifies where the component is to be placed. The default location is BorderLayout.CENTER.

  4. The actionPerformed() method removes the component that the user clicked and forces the window to be redrawn. The object cast is needed because the getSource() method returns a generic Object and the remove() method requires a Component.

  5. BorderLayout preserves the width of components in the EAST and WEST positions and the height of components in the NORTH and SOUTH positions. The component in the CENTER is stretched to fill the remaining space. This can be seen by resizing the window during program execution.

 

FlowLayout

Example:

import java.awt.*;
import java.awt.event.*;

public class App extends Frame implements WindowListener, ActionListener {

  Button b1, b2, b3, b4;

  public static void main(String[] args) {
    App myWindow = new App("Flow Layout");
    myWindow.setSize(200,200);
    myWindow.setVisible(true);
  }

  public App(String title) {
    super(title);
    setLayout(new FlowLayout());
    addWindowListener(this);
    b1 = new Button("Button One");
    add(b1);
    b1.addActionListener(this);
    b2 = new Button("Button Two");
    add(b2);
    b2.addActionListener(this);
    b3 = new Button("This is Button Three");
    add(b3);
    b3.addActionListener(this);
    b4 = new Button("Button Four");
    add(b4);
    b4.addActionListener(this);
  }

  public void actionPerformed(ActionEvent e) {
    remove((Component)e.getSource());
    validate();
  }

  public void windowClosing(WindowEvent e) {
    dispose();
    System.exit(0);
  }

  public void windowOpened(WindowEvent e) {}
  public void windowActivated(WindowEvent e) {}
  public void windowIconified(WindowEvent e) {}
  public void windowDeiconified(WindowEvent e) {}
  public void windowDeactivated(WindowEvent e) {}
  public void windowClosed(WindowEvent e) {}
}

Notes:

  1. The sample declares four Button object references (b1 through b4)

  2. In the constructor, setLayout() is called to set FlowLayout for the Frame 

  3. With FlowLayout, the add() method simply adds components to the container in a first-come, first-served basis

  4. The actionPerformed() method removes the component that the user clicked and forces the window to be redrawn. The object cast is needed because the getSource() method returns a generic Object and the remove() method requires a Component.

  5. FlowLayout preserves the height and width of all components. Resizing the window during program execution will result in components being rearranged but not resized.

 

GridLayout

Example:

import java.awt.*;
import java.awt.event.*;

public class App extends Frame implements WindowListener, ActionListener {

  Button b1, b2, b3, b4, b5, b6;

  public static void main(String[] args) {
    App myWindow = new App("Grid Layout (2 x 3)");
    myWindow.setSize(250,250);
    myWindow.setVisible(true);
  }

  public App(String title) {
    super(title);
    setLayout(new GridLayout(2,3));
    setFont(new Font("San Serif", Font.BOLD, 20));
    addWindowListener(this);
    b1 = new Button("1");
    add(b1);
    b1.addActionListener(this);
    b2 = new Button("2");
    add(b2);
    b2.addActionListener(this);
    b3 = new Button("3");
    add(b3);
    b3.addActionListener(this);
    b4 = new Button("4");
    add(b4);
    b4.addActionListener(this);
    b5 = new Button("5");
    add(b5);
    b5.addActionListener(this);
    b6 = new Button("6");
    add(b6);
    b6.addActionListener(this);
  }

  public void actionPerformed(ActionEvent e) {
    remove((Component)e.getSource());
    validate();
  }

  public void windowClosing(WindowEvent e) {
    dispose();
    System.exit(0);
  }

  public void windowOpened(WindowEvent e) {}
  public void windowActivated(WindowEvent e) {}
  public void windowIconified(WindowEvent e) {}
  public void windowDeiconified(WindowEvent e) {}
  public void windowDeactivated(WindowEvent e) {}
  public void windowClosed(WindowEvent e) {}
}

Notes:

  1. The sample declares six Button object references (b1 through b6)

  2. In the constructor, setLayout() is called to set a GridLayout having 2 rows and 3 columns for the Frame 

  3. With FlowLayout, the add() method simply adds components to the next cell in the container (going left to right, row by row)

  4. The actionPerformed() method removes the component that the user clicked and forces the window to be redrawn. The object cast is needed because the getSource() method returns a generic Object and the remove() method requires a Component.

  5. GridLayout ignores the height and width of all components. They are resized to fit their cell. Resizing the window during program execution will result in components being resized but not rearranged.

 

Satisfying complex GUI requirements

Nested containers can be used to satisfy many complex graphical interface requirements. For example, a Panel with a GridLayout might be placed in the center of a Frame having a BorderLayout to produce something like this:

North

West

 

1

 

2

3

East

 

4

 

5

6

 

7

 

8

9

South

The possibilities are nearly infinite.

 

Review questions

  1. Which of these layout managers can be used with a single container to show 6 components at one time?  (choose two)

  1. BorderLayout

  2. FlowLayout

  3. GridLayout

  1. If myPanel references a Panel object, code a single statement to set the panel's layout manager so it will display components in three rows of five columns each.

  1. Assume that myFrame references a Frame having a BorderLayout. Which of the following would correctly add a Button object to the center of myFrame?  (choose two)

  1. myFrame.add(new Button("Hello"));

  2. myFrame.add("Hello");

  3. myFrame.add(new Button("Hello"), CENTER);

  4. myFrame.add(new Button("Hello"), BorderLayout.CENTER);

  5. myFrame.add(new Button("Hello"), 1, 1);

  1. Which one statement is true about attempting to compile and run the application shown below? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.awt.*;
import java.awt.event.*;

public class App extends Frame implements WindowListener{

  public static void main(String[] args) {
    App myApp = new App();
    myApp.setVisible(true);
  }

  public App() {
    setSize(300, 300);
    addWindowListener(this);
    setFont(new Font("San Serif", Font.BOLD, 36));
    Button b = new Button("XYZ");
    add(b, BorderLayout.EAST);
  }

  public void windowClosing(WindowEvent e) {
    dispose();
    System.exit(0);
  }

  public void windowOpened(WindowEvent e) {}
  public void windowActivated(WindowEvent e) {}
  public void windowIconified(WindowEvent e) {}
  public void windowDeiconified(WindowEvent e) {}
  public void windowDeactivated(WindowEvent e) {}
  public void windowClosed(WindowEvent e) {}
}
  1. Compilation fails at line 16 because no layout manager has been specified

  2. Compilation succeeds but nothing is displayed

  3. A single button with the text "XYZ" will entirely fill the window on the screen

  4. A single button with the text "XYZ" will occupy the right side of the window on the screen. The button will be taller than it is wide.

  5. A single button with the text "XYZ" will occupy the right side of the window on the screen. If the window is resized to be wider, the button will also become wider.