All Categories :
Java
Chapter 21
Checkboxes, Choices, and Lists
CONTENTS
This chapter covers the details of using the Checkbox,
Choice, and List
classes. It shows you how to create and use objects of these classes
and how to create custom components that simplify the use of these
GUI controls. When you finish this chapter, you will be able to
effectively use checkboxes, radio buttons, choices, and lists
in your Java window programs.
Checkboxes are a common type of GUI control. They are typically
used in form-like windows to simplify yes/no or true/false selections.
The user checks a checkbox to indicate yes or true, and leaves
it unchecked to indicate no or false.
The name of the Checkbox
class is somewhat misleading in that Checkbox
objects are used to implement traditional checkboxes as well as
radio buttons.
Radio buttons are similar to traditional checkboxes in
that they are in either an on or off state. They are different
from traditional checkboxes in that only one radio button in a
group may be on at a given time. They are aptly named after the
buttons on a car radio, which can only be used to select a single
radio channel at a given time.
When Checkbox objects are
used as radio buttons, they are associated with a CheckboxGroup
object that enforces mutual exclusion among the Checkbox
objects in its group.
Checkboxes, like menus, are easy to use but tedious to construct
and organize. The CheckboxPanel
class provides a more convenient approach to creating and organizing
checkboxes. (See Listing 21.1.) Typically, checkboxes are created
in groups and organized in a panel that is given a title. The
CheckboxPanel class provides
a constructor for quickly creating objects of this type. It also
provides access methods for getting and setting the value of an
individual checkbox within the panel, based on the checkbox's
label.
Listing 21.1. The CheckboxPanel
class source code.
package jdg.ch21;
import java.awt.*;
public class CheckboxPanel extends Panel {
public static int HORIZONTAL = 0;
public static int VERTICAL = 1;
public CheckboxPanel(String title,String labels[],int orientation)
{
super();
int length = labels.length;
if(orientation == HORIZONTAL) setLayout(new GridLayout(1,length+1));
else setLayout(new GridLayout(length+1,1));
add(new Label(title));
for(int i=0;i<length;++i) add(new Checkbox(labels[i]));
}
public CheckboxPanel(String title,String labels[],boolean
state[],
int orientation) {
super();
int length = labels.length;
if(orientation == HORIZONTAL) setLayout(new GridLayout(1,length+1));
else setLayout(new GridLayout(length+1,1));
add(new Label(title));
for(int i=0;i<length;++i){
Checkbox checkBox = new Checkbox(labels[i]);
checkBox.setState(state[i]);
add(checkBox);
}
}
public boolean getState(String label) {
Checkbox boxes[] = (Checkbox[])getComponents();
for(int i=0;i<boxes.length;++i)
if(label.equals(boxes[i].getLabel())) return
boxes[i].getState();
return false;
}
public void setState(String label,boolean state) {
Checkbox boxes[] = (Checkbox[])getComponents();
for(int i=0;i<boxes.length;++i)
if(label.equals(boxes[i].getLabel())) boxes[i].setState(state);
}
}
Two CheckboxPanel constructors
are provided. The first constructor uses a title
string for the panel, an array of labels[]
to be associated with checkboxes, and an orientation
parameter that specifies whether the panel is to be organized
in a vertical or horizontal fashion.
A GridLayout object is used
to organize the Label and
Checkbox objects placed within
the panel. The title Label
is added at the top of vertical panels and on the left side of
horizontal panels. Then the checkboxes are created, one at a time,
and fill in the rest of the panel.
The second constructor is similar to the first constructor, except
that it uses an additional state[]
array to set the initial state of the checkboxes that are added
to the panel. The state of each checkbox is set using the setState()
method of the Checkbox class.
The getState() method takes
the label of a checkbox as its parameter and searches the checkboxes
contained in the panel for one whose label matches the specified
label. It then returns the state of this checkbox. If no matching
checkbox is found, it returns false.
The setState() method is
similar to the getState()
method. It is used to update a checkbox with a given label.
Radio buttons are created using the Checkbox
class and are transformed from checkboxes into radio buttons when
they are associated with a CheckboxGroup
object. A CheckboxGroup can
be assigned with the Checkbox
constructor or using the setCheckboxGroup()
method. Only one object in the checkbox group is allowed to be
set at any given time.
The CheckboxGroupPanel class
extends the CheckboxPanel
class to work with radio buttons. Its source code is shown in
Listing 21.2.
Listing 21.2. The source code for the CheckboxGroupPanel
class.
package jdg.ch21;
import java.awt.*;
public class CheckboxGroupPanel extends CheckboxPanel {
public CheckboxGroupPanel(String title,String labels[],int
orientation) {
super(title,labels,orientation);
putInGroup();
}
public CheckboxGroupPanel(String title,String labels[],boolean
state[],
int orientation) {
super(title,labels,state,orientation);
putInGroup();
}
void putInGroup() {
Component components[] = getComponents();
int length = components.length;
CheckboxGroup group = new CheckboxGroup();
for(int i=1;i<length;++i){
Checkbox checkBox = (Checkbox) components[i];
checkBox.setCheckboxGroup(group);
}
}
}
The Checkbox panel constructors
are overridden to place the checkboxes in the panel in a single
group. If the second constructor is used, only one checkbox should
be specified as being in the on state.
The putInGroup() method uses
the getComponents() method
inherited from the Container
class to create an array of the components contained in the panel.
It creates a CheckboxGroup
object and then indexes through the array, putting all checkboxes
into this group using the setCheckboxGroup()
method. The first component is skipped because it is the title
of the panel.
The CheckboxApp program illustrates
the use of the CheckboxPanel
and CheckboxGroupPanel classes.
Its source code is shown in Listing 21.3.
Listing 21.3. The source code for the CheckboxApp
program.
import java.awt.*;
import jdg.ch20.MyMenu;
import jdg.ch20.MyMenuBar;
import jdg.ch20.MessageDialog;
import jdg.ch21.CheckboxPanel;
import jdg.ch21.CheckboxGroupPanel;
public class CheckboxApp extends Frame {
MyMenuBar menuBar;
MessageDialog dialog;
CheckboxPanel checkboxPanel;
CheckboxGroupPanel checkboxGroupPanel;
public static void main(String args[]){
CheckboxApp app = new CheckboxApp();
}
public CheckboxApp() {
super("CheckboxApp");
setup();
pack();
resize(minimumSize());
show();
}
void setup() {
setBackground(Color.white);
setupMenuBar();
setupCheckboxes();
}
void setupMenuBar(){
Object menuItems[][] = {
{"File","Exit"},
};
menuBar = new MyMenuBar(menuItems);
setMenuBar(menuBar);
}
void setupCheckboxes(){
setLayout(new GridLayout(1,2));
String sports[] = {"Baseball","Basketball","Football","Hockey","Soccer"};
checkboxPanel = new CheckboxPanel("What team
sports do you like? ",
sports,CheckboxPanel.VERTICAL);
add(checkboxPanel);
String ages[] = {"under 20","20 - 39","40
- 59","60 - 79","80 and over"};
checkboxGroupPanel = new CheckboxGroupPanel("What
is your age? ",
ages,CheckboxPanel.VERTICAL);
add(checkboxGroupPanel);
}
public boolean handleEvent(Event event) {
if(event.id==Event.WINDOW_DESTROY){
if(event.target instanceof MessageDialog) return
true;
System.exit(0);
return true;
}else if(event.id==Event.ACTION_EVENT){
if(event.target instanceof MenuItem){
if("Exit".equals(event.arg)){
System.exit(0);
return true;
}
}else if(event.target instanceof Checkbox){
String status;
Checkbox checkbox = (Checkbox)event.target;
if(checkbox.getState()) status = "You
checked: ";
else status = "You unchecked: ";
String text[] = {status+checkbox.getLabel()+"
"};
String buttons[] = {"OK"};
dialog = new MessageDialog(this,"Guess
what?",true,text,buttons);
dialog.show();
return true;
}
}
return false;
}
}
When you execute the program, it displays the window shown in
Figure 21.1. The left side of the window
displays a CheckboxPanel
object, and the right side displays a CheckboxPanelGroup
object. Notice that traditional checkboxes are displayed on the
left, and radio buttons are displayed on the right.
Figure 21.1 : The CheckboxApp opening window.
Click on the Basketball checkbox, as shown in Figure 21.2.
The checkbox is checked and the dialog box shown in Figure 21.3
is displayed as the result of handling this event. Click on the
Basketball checkbox again, and the dialog box shown in Figure 21.4
is displayed. The purpose of this type of dialog box is to illustrate
checkbox event handling. It is not normally part of any application
that uses checkboxes because the checkbox display indicates the
state of a checkbox.
Figure 21.2 : Checking Basketball.
Figure 21.3 : You checked Basketball
Figure 21.4 : You unchecked Basketball.
Go ahead and check your favorite sports, and then turn your attention
to the radio buttons. Select your age group, as shown in Figure 21.5.
The program notifies you of your selection. Go ahead and select
another age group, as shown in Figure 21.6.
Notice that you can't select more than one age group at a given
time. That's the idea behind radio buttons.
Figure 21.5 : Select your age group
Figure 21.6 : Now select a different age group
The CheckboxApp program makes
use of several custom components that you've built so far, including
the MyMenu, MyMenuBar,
MessageDialog, CheckboxPanel,
and CheckboxGroupPanel classes.
Try rewriting this program without using these classes and you'll
find out how time- consuming and tedious it can be to write programs
without custom classes. You should now be getting used to using
this class-building approach to simplify your Java programming.
The setupCheckboxes() method
sets up the checkbox and radio button panels displayed in the
previous figures. A GridLayout
object is used to organize the main application window. The checkboxPanel
variable is assigned the CheckboxPanel
object that is created using the sports[]
array, and the checkboxGroupPanel
variable is assigned the CheckboxGroupPanel
object that is created using the ages[]
array. Both panels are then added to the Frame
object being constructed. That's all the code required to create
the GUI controls shown in Figure 21.1.
The handleEvent() method
looks to see if the target of an ACTION_EVENT
is an instance of the Checkbox
class. This will be true for both checkboxes and radio buttons.
It then retrieves the checkbox from the event.target
variable and uses the getState()
method to obtain the state of the Checkbox
object. Then it retrieves the label of the Checkbox
object using the getLabel()
method and passes this information to the user via a MessageDialog
object.
The Choice class allows Motif-style
choice lists to be used in Java window programs. These GUI controls
are also supported in Windows 95 and NT programs. A choice
list is a pull-down menu that allows a user to select a single
item from a list. When a choice selection is made, an ACTION_EVENT
is generated, and the program is then able to respond to that
selection. Choices are like menus that are placed in the middle
of a window.
MyChoice is a short and sweet
class that simplifies the construction of a Choice
object. Its source code is shown in Listing 21.4.
Listing 21.4. The source code for the MyChoice
class.
package jdg.ch21;
import java.awt.*;
public class MyChoice extends Choice {
public MyChoice(String labels[]) {
super();
int length = labels.length;
for(int i=0;i<length;++i) {
try {
addItem(labels[i]);
}catch (NullPointerException ex) {
addItem("");
}
}
}
}
Rather than constructing a Choice
object and adding all of the items in the choice list, the MyChoice
constructor takes an array of labels and adds them to the Choice
object as it is constructed. The addItem()
method of the Choice class
throws the NullPointerException
and is handled by adding a blank item to the choice list when
a null pointer is encountered.
The List class is a tad more
sophisticated that the Choice
class. It is similar in that it allows a user to select from a
list of items that are displayed in a window component. It is
different because it provides the capability to support multiple
menu selections, to specify the size of the list window, and to
dynamically update the list during program execution.
The List class provides two
constructors. The default constructor takes no parameters. The
second constructor specifies the number of visible rows to be
identified and whether multiple selections are allowed.
The access methods supported by the List
class are also more extensive than the Choice
class. In particular, the delItem(),
clear(), and replaceItem()
methods allow List objects
to be dynamically updated.
The MyList class is very
similar to the MyChoice class
in that it enables a list to be constructed using an array of
list items. (See Listing 21.5.) The MyList
constructor also allows the number of rows displayed in the list
and the multiple-selection parameter to be specified. The MyList
constructor sets the foreground and background colors of the list
box that is displayed. This is used to override any colors that
might be set for the foreground and background of the list's container.
Listing 21.5. The source code for the MyList
class.
package jdg.ch21;
import java.awt.*;
public class MyList extends List {
public MyList(int rows,boolean multiple,String labels[])
{
super(rows,multiple);
int length = labels.length;
for(int i=0;i<length;++i) {
try {
addItem(labels[i]);
}catch (NullPointerException ex) {
addItem("");
}
}
setBackground(Color.white);
setForeground(Color.black);
}
}
The ChoiceListApp program
illustrates the use of the MyChoice
and MyList classes. (See
Listing 21.6.) It provides the capability to decide what you want
to eat for your next meal and can be very handy when a moment
of indecision arrives. The following source code lists only a
basic set of menu items, but additional menu items can be added
easily.
Listing 21.6. The source code for the ChoiceListApp
program.
import java.awt.*;
import jdg.ch20.MyMenu;
import jdg.ch20.MyMenuBar;
import jdg.ch21.MyChoice;
import jdg.ch21.MyList;
public class ChoiceListApp extends Frame {
MyMenuBar menuBar;
MyChoice mealChoice;
MyList currentList;
MyList mealList[];
String meals[] = {"Breakfast","Lunch","Dinner"};
String mealChoices[][] = {
{"pancakes","eggs","bacon","ham","sausage","cereal",
"toast","coffee","juice"},
{"pizza","hamburger","hot
dog","burrito","salad","fries",
"chips","soda","milk"},
{"spaghetti","carne asada","barbequed
chicken","soup","salad",
"bread","wine","beer","soda","milk"}
};
TextField text;
public static void main(String args[]){
ChoiceListApp app = new ChoiceListApp();
}
public ChoiceListApp() {
super("ChoiceListApp");
setup();
pack();
resize(275,175);
show();
}
void setup() {
setBackground(Color.white);
setupMenuBar();
setupChoice();
setupLists();
text = new TextField(40);
add("North",new Label("Place your order:"));
add("South",text);
add("West",mealChoice);
currentList = mealList[0];
add("East",currentList);
}
void setupMenuBar(){
Object menuItems[][] = {
{"File","Exit"},
};
menuBar = new MyMenuBar(menuItems);
setMenuBar(menuBar);
}
void setupChoice(){
mealChoice = new MyChoice(meals);
}
void setupLists(){
mealList = new MyList[meals.length];
for(int i=0;i<meals.length;++i)
mealList[i] = new MyList(5,true,mealChoices[i]);
}
public boolean handleEvent(Event event) {
if(event.id==Event.WINDOW_DESTROY){
System.exit(0);
return true;
}else if(event.id==Event.ACTION_EVENT){
if(event.target instanceof MenuItem){
if("Exit".equals(event.arg)){
System.exit(0);
return true;
}
}else if(event.target instanceof Choice){
for(int i=0;i<meals.length;++i)
if(meals[i].equals(event.arg)){
remove(currentList);
currentList = mealList[i];
add("East",currentList);
text.setText(meals[i]);
}
show();
return true;
}else if(event.target instanceof List){
updateTextField();
return true;
}
}else if(event.id==Event.LIST_SELECT || event.id==Event.LIST_DESELECT){
updateTextField();
return true;
}
return false;
}
void updateTextField() {
String order = mealChoice.getSelectedItem()+": ";
String items[] = currentList.getSelectedItems();
for(int i=0;i<items.length;++i) order += items[i]+"
";
text.setText(order);
}
}
Make sure that you have food on hand when you run the ChoiceListApp
program. Its opening window is shown in Figure 21.7.
Figure 21.7 : The ChoiceListApp opening window.
The choice list shown on the left side of the window is used to
select a meal. This selection determines what menu items are displayed
in the list shown on the right side of the window. More than one
item can be selected from the entrée list. The text field
on the bottom of the screen identifies the selections that you
have made. Go ahead and select Lunch from the choice list, as
shown in Figure 21.8. Notice that the
entrée list is updated with some typical lunch items. The
text field tells you that you are now ordering lunch.
Figure 21.8 : Selecting lunch.
Go ahead and select some menu items from the entrée list.
They are displayed in the text field, as shown in Figure 21.9.
Figure 21.9 : Ordering lunch.
Now select Dinner from the choice list and select some dinner
entrées, as shown in Figure 21.10.
The text field is updated to list your new selections.
Figure 21.10 : Selecting another meal.
The ChoiceListApp program
declares several field variables. The menuBar
variable is the now-standard variable used to identify the program's
menu bar. The mealChoice
variable is used to refer to the MyChoice
object that displays the meals identified in the meals[]
array. Two MyList variables
are declared. The mealList[]
array holds the three MyList
objects used for breakfast, lunch, and dinner. These items are
stored in the mealChoices[]
array. The currentList variable
points to the current menu entrée list being displayed.
The text variable refers
to the TextField object displayed
at the bottom of the window.
The main() method and ChoiceListApp()
constructor follow the pattern that's been developed so far. The
window is resized to make its display more visually appealing.
A GridBagLayout layout would
have been more appropriate for this type of application, but the
overhead of implementing it would obscure the important points
associated with the MyChoice
and MyList classes.
The setup() method sets up
the background and menu bar and then invokes the setupChoice()
and setupLists() methods
to set up the MyChoice and
MyList objects. The text
field is initialized to be 40 characters wide, and then the user-interface
objects are placed in the appropriate places in the ChoiceListApp
window.
The setupChoice() method
constructs the mealChoice
object using a simple, one-line constructor. The setupLists()
method sets up the mealList
object by indexing through the mealChoices[]
array and setting up the individual MyList
objects.
The handleEvent() method
looks for events of type ACTION_EVENT
that are instances of the Choice
class. It handles them by finding the element of the meals[]
array that was selected and using it to select the next mealList[]
element to be displayed as the currentList.
The old list is removed, and a new currentList
object is added. The text field is then set to the meals[]
element that was selected. Note that this approach of removing
the list and replacing it with a new one is less elegant than
updating the list as it is displayed.
The handleEvent() method
processes ACTION_EVENT, which
occurs when the user double-clicks on a list item. It invokes
the updateTextField() method
to update the text that is displayed in the text field at the
bottom of the window's display. It also handles the LIST_SELECT
and LIST_DESELECT events
in the same fashion.
The updateTextField() method
retrieves the currently selected item in the MyChoice
object referred to by mealChoice
using the getSelectedItem()
method of the Choice class.
This String object is used
to build the text display by identifying the currently selected
meal. The getSelectedItems()
method of the List class
is used to return a list of all items selected in the currently
displayed MyChoice object
referred to by the currentList
variable. These items are then added to the text field display.
This chapter shows you how to use the Checkbox,
Choice, and List
classes. It describes their available constructors and access
methods and shows you how to use them as the basis for creating
custom GUI components. Chapter 22, "Text
and Fonts," shows you how to work with these features.

Contact
reference@developer.com with questions or comments.
Copyright 1998
EarthWeb Inc., All rights reserved.
PLEASE READ THE ACCEPTABLE USAGE STATEMENT.
Copyright 1998 Macmillan Computer Publishing. All rights reserved.