Using CardLayout

 

Overview

A container can easily become too large, too complex, or cluttered with too many components. One solution to this problem is to not display all the components at the same time. By using CardLayout as the layout manager of a container, the user can be allowed to flip through a stack of the container's components.

 

CardLayout

CardLayout myCardLayout = new CardLayout();

Once instantiated, a CardLayout object may be used to manage a container as shown by the code

Panel cards = new Panel();
cards.setLayout(myCardLayout);

which creates a Panel object and establishes its layout manager. When a component is added to the container, it becomes another card within the container's stack. For example, if b1 and b2 are previously defined Button objects they may be added to the container by coding

cards.add(b1, "Button 1");
cards.add(b2, "Button 2");

where the string parameter is used as an identifier for the component. Because it was added first, the b1 button would be the only component displayed when the container is made visible. To display the b2 button one could code either

myCardLayout.next(cards);

or

myCardLayout.show(cards, "Button 2");

The first technique is used to flip through the container's cards in the order in which they were added to the container. The second technique is used to go directly to a specific card within the container.

Method

Usage

first()

Flips to the first card in the named container

last()

Flips to the last card in the named container

next()

Flips to the next card in the named container

previous()

Flips to the previous card in the named container

show()

Flips to a specified card in the named container

Note that these methods are non-static. You are required to instantiate a CardLayout object in order to use them. Consult the help facility of your Java development environment or the Java API for more details.

 

A sample applet that uses CardLayout

The following applet uses CardLayout to manage and display a container consisting of several labels:

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

public class App extends Applet {

  // Object references and variables to support "card" processing.

  Panel cards;
  CardLayout myCardLayout;
  int cardIndex;

  // Object references to support user controls.

  Panel controls;
  Button next;
  Button previous;
  Choice pickOne;

  // Applet initialization.

  public void init() {
  resize(450, 350);
  setLayout(new BorderLayout());

  // Instantiate objects and variables to support "card" processing.

  cards = new Panel();
  myCardLayout = new CardLayout();
  cardIndex = 0;

  // Instantiate objects to support user controls.

  next = new Button(">");
  previous = new Button("<");
  pickOne = new Choice();
  controls = new Panel();

  // Build the container of "cards" and add it to the applet's panel.

  cards.setLayout(myCardLayout);
  Label x = new Label("Hello World!");
  x.setBackground(Color.black);
  x.setForeground(Color.white);
  x.setFont(new Font("Serif", Font.PLAIN, 36));
  x.setAlignment(Label.CENTER);
  cards.add(x, "Card 1");
  Label y = new Label("Java is Fun!");
  y.setBackground(Color.white);
  y.setForeground(Color.black);
  y.setFont(new Font("Serif", Font.PLAIN, 36));
  y.setAlignment(Label.CENTER);
  cards.add(y, "Card 2");
  Label z = new Label("Ferris State University");
  z.setBackground(Color.red);
  z.setForeground(Color.yellow);
  z.setFont(new Font("Serif", Font.PLAIN + Font.BOLD, 36));
  z.setAlignment(Label.CENTER);
  cards.add(z, "Card 3");
  add(cards);

  // Build the container of user controls and add it to the applet's
  // panel.

  controls.setLayout(new GridLayout(1, 3));
  previous.setFont(new Font("SanSerif", Font.BOLD, 18));
  previous.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent e) {

        // Display the previous "card" in the container and make
        // it the current selection in the Choice component

        myCardLayout.previous(cards);
        if (cardIndex > 0) {
          cardIndex--;
        }
        else {
          cardIndex = cards.getComponentCount() - 1;
        }
        pickOne.select(cardIndex);
      }
    }
  );
  controls.add(previous);
  pickOne.addItem("Card 1");
  pickOne.addItem("Card 2");
  pickOne.addItem("Card 3");
  pickOne.addItemListener(
    new ItemListener() {
      public void itemStateChanged(ItemEvent e) {

        // Display the selected "card" within the container and
        // update the current card index being displayed.

        myCardLayout.show(cards, pickOne.getSelectedItem());
        cardIndex = pickOne.getSelectedIndex();
      }
    }
  );
  controls.add(pickOne);
  next.setFont(new Font("SanSerif", Font.BOLD, 18));
  next.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent e) {

        // Display the next "card" in the container and make
        // it the current selection in the Choice component

        myCardLayout.next(cards);
        if (cardIndex < cards.getComponentCount() - 1) {
          cardIndex++;
        }
        else {
          cardIndex = 0;
        }
      pickOne.select(cardIndex);
      }
    }
  );
  controls.add(next);
  add(controls, BorderLayout.SOUTH);
  }
}

Notes:

  1. Rather than implement listener interfaces at the class level, inner listeners are registered and defined for components that fire events.

  2. A CardLayout object (myCardLayout) is created and used for the container of "cards" (cards). This is necessary because an object is required to manage the container. Methods of the CardLayout class, such as previous() and next(), are instance methods (they are not static).

 

Lab exercise for Ferris students

E-mail your answers to this assignment no later than the due date listed in the class schedule.

 

Review questions

  1. Assume that a CardLayout object named someLayout has been designated as the layout manager for a Panel object named somePanel and that somePanel has been populated with named components. Which one of the following statements might be used to display a specific component within somePanel?

  1. someLayout.next(somePanel);

  1. CardLayout.next(somePanel);

  2. someLayout.show(somePanel, "17");

  3. CardLayout.show(somePanel, "17");

  4. someLayout.show(somePanel, 17);

  1. Assume that a properly populated container having 5 objects is using a CardLayout layout manager. If the currently displayed component is the first component that was added to the container, what will happen if an attempt is made to show the previous component?

  1. a compile error will result

  1. a run time error will occur

  2. nothing will be displayed

  3. the fifth component added to the container will be displayed

  4. the first component added to the container will still be displayed

  1. Assume that somePanel is a container having a CardLayout layout manager and data is the reference of a TextField object. Which of the following statements would add the TextField object to the container in such a way that it may be directly displayed when needed?

    1. somePanel.add(data, "data");

    1. somePanel.add(data, 5);

    2. somePanel.add(5, data);

    3. somePanel.add(data);

    4. add(somePanel, data, "data");

  1. True or False: When using a CardLayout layout manager for a container, the container's area on the screen will never display more than one component.

  1. True

  2. False