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
Displays only one of the container's components at a time. This may be an individual component (such as a Canvas containing a graphic) or a container of related components (such as a Panel of Button, Label, and TextField objects). The latter is possible because a container is a component.
Treats each component in the container as a card and the container as a stack of cards. The first component added to the container is the visible component when the container is first displayed.
Has a set of methods (to be covered shortly) that allow an application to flip through the container's cards sequentially, or to show a specified card for fast random access.
Overrides the preferred size of a component to completely fill the area of the container
Has overloaded constructors. The most frequently used requires no parameters. For example, to construct a CardLayout object one might code:
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.
Contains a number of instance methods. The following are most useful:
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:
Rather than implement listener interfaces at the class level, inner listeners are registered and defined for components that fire events.
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
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?
someLayout.next(somePanel);
CardLayout.next(somePanel);
someLayout.show(somePanel, "17");
CardLayout.show(somePanel, "17");
someLayout.show(somePanel, 17);
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?
a compile error will result
a run time error will occur
nothing will be displayed
the fifth component added to the container will be displayed
the first component added to the container will still be displayed
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?
somePanel.add(data, "data");
somePanel.add(data, 5);
somePanel.add(5, data);
somePanel.add(data);
add(somePanel, data, "data");
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.
True
False