Lesson 12.3 Checkboxes
Checkboxes & Radio Buttons
For your homework for this lesson, you'll be improving a Java painting program known as "Scrawler." The purpose of the homework is to allow you to use some of the different AWT components that you haven't had any experience with yet.
Your new SuperScrawler Applet will have the following features:
- Different colored pens
- Different width pens
- Regular and XOR painting modes
- Lines with rubber-banding
- Figures (Rectangles and Ovals) with rubber-banding
In this lesson, and the next, I'll try to make sure you have all the information you need to complete the program successfuly.
Mouse Cursors
In the AWT, every component has a cursor associated with it. This cursor is represented by the Cursor class. [Note: the Cursor class is only available in Java 1.1 and later.]
You can retrieve a component's cursor using the getCursor() method, and you can set a new cursor by using setCursor(). When you call setCursor(), you have to pass a Cursor object as an argument.
Here's a short applet, TestCursor.java, that shows how this works. The applet creates a new cursor using one of the twelve predefined identifiers in the Cursor class. Instead of calling the Cursor() constructor, the applet uses the factory method getPredefinedCursor().
|
TestCursor.java
|
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class TestCursor extends Applet
implements ActionListener
{
Cursor crsCross =
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
Button btnCross = new Button("CROSSHAIR_CURSOR");
Cursor crsHand =
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
Button btnHand = new Button("HAND_CURSOR");
Cursor crsDef =
Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
Button btnDef = new Button("DEFAULT_CURSOR");
public void init()
{
btnHand.setCursor(crsHand);
btnCross.setCursor(crsCross);
btnDef.setCursor(crsDef);
btnHand.addActionListener(this);
btnCross.addActionListener(this);
btnDef.addActionListener(this);
add(btnHand);
add(btnCross);
add(btnDef);
}
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == btnHand)
{
setCursor(crsHand);
}
else if (ae.getSource() == btnCross)
{
setCursor(crsCross);
}
else
{
setCursor(crsDef);
}
}
}
|
When you move your mouse over each of the buttons shown in the applet, you'll find that the cursor changes from the default arrow, to the cross-hair cursor, to a hand cursor. What the actual images look like will depend on your platform.
If you press one of the buttons, the Hand Cursor button, for instance, you'll find that both the background of the applet and the Default Cursor button adopt the new style, but the Crosshair button retains its distinctive style.
A similar thing happens if you press the Crosshair button. Now the background and default button use the Crosshair, but the Hand button retains its style. As you can see, the Default button uses the cursor style of its container.
Checkboxes
Checkboxes are user-interface components that represent either an on-off selection or a set of non-exclusive options.
The actual shape of a checkbox depends on the platform you're using. Typically it's a square box with an "x" inside if the option is selected, and a hollow box if the option is unselected.
Some platforms, such as Windows, support a middle, "maybe" state for checkboxes, but Java doesn't support this option.
The Checkbox Class
To create a Checkbox object, use one of these two constructors:
Checkbox one = new Checkbox("Option 1");
Checkbox two = new Checkbox("Option 2", true); |
The first constructor creates an initially unchecked Checkbox object, while the second is initially checked.
Checkbox Events
In Java 1.0, Checkboxes generated action events which were handled in the action() method, just like Button clicks. Under Java 1.1 Checkbox objects do not generate action events; instead, they generate ItemEvents.
To subscribe to the ItemEvents generated by a Checkbox, you must do these three things:
- Add implements ItemListener to your class header.
- Send the Checkbox object an addItemListener() message.
- Write an itemStateChanged(ItemEvent) method.
Here's an example that shows you how to respond to these ItemEvents. The applet creates three Checkbox objects, and then displays the event information that is generated when the Checkbox is clicked; the information is displayed inside a TextArea:
|
TestCheckbox.java
|
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class TestCheckbox extends Applet
implements ItemListener
{
private TextArea ta = new TextArea();
public void init()
{
setLayout(new BorderLayout());
add("North", makeCheckPanel());
add("Center", ta);
}
public Panel makeCheckPanel()
{
Panel p = new Panel();
Checkbox cb = new Checkbox("Cream", false);
cb.addItemListener(this);
p.add(cb);
cb = new Checkbox("Sugar", false);
cb.addItemListener(this);
p.add(cb);
cb = new Checkbox("Licorice-Lime", true);
cb.addItemListener(this);
p.add(cb);
return p;
}
public void itemStateChanged(ItemEvent ie)
{
ta.append("ItemEvent = " + ie + "\n");
}
}
|
Checkbox Methods
Most of the time, you really don't care if someone checks or unchecks your Checkbox. Instead, you just want to find out if it is currently checked when it comes time to use it.
The Checkbox class has two state-related methods that allow this. If you want to find out if your Checkbox is checked, then use the getState() method like this:
| boolean isOn = onChk.getState(); |
If getState() returns true, then the Checkbox is checked; if it returns false, then the Checkbox is unchecked.
You can also set the state programmatically using the setState() method like this:
| onChk.setState(true); // Check it |
Here's a short example program, CheckState.java, that paints a large oval if the Checkbox bigDot is selected, and a smaller one otherwise.
|
CheckState.java
|
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class CheckState extends Applet
implements ActionListener
{
private Checkbox bigDot = new Checkbox("Large", true);
private Button paintBtn = new Button("Paint");
public void init()
{
setLayout(new BorderLayout());
add("North", bigDot);
add("South", paintBtn);
paintBtn.addActionListener(this);
}
public void paint(Graphics g)
{
int w = getSize().width;
int h = getSize().height;
if (bigDot.getState())
g.drawOval(w/3, h/3, w/3, h/3);
else
g.drawOval((w/5)*2, (h/5)*2, w/5, h/5);
}
public void actionPerformed(ActionEvent ae)
{
repaint();
}
}
|
Radio Buttons
Radio buttons are close kin to checkboxes; in Java, they're both implemented using the same class. The main difference is that a checkbox represents a non-exclusive choice: if you have ten checkboxes, all of them may be checked, none of them may be checked, or anything in between.
Radio buttons represent the exclusive side of the family. If you have four radio buttons in a group, one, and only one, can be checked at any given time. [It is possible for none of the radio buttons to be checked, but this is a design flaw.]
The actual images displayed when you create a set of radio buttons depends on the platform on which you run your program. If run under Motif, you'll see the little diamonds favored there. More commonly, on Windows and the Mac, you'll see a group of small circles, with one of the circles filled.
What? No RadioButton Class?
It's true: there is no RadioButton class. Instead, to create a set of radio buttons, you first need to create a CheckboxGroup object which acts to tie a group of CheckBox objects together, and which lets Java know that it is supposed to draw radio buttons rather than regular check boxes.
Here's how you start:
| CheckboxGroup cbg = new CheckboxGroup(); |
That wasn't too hard, was it? Next, you create your Checkbox items, using this constructor:
| Checkbox yes = new Checkbox("Yes", true, cbg); |
Here's a short example program, RadioOne.java, that creates several radio buttons. Note how the Panels and GridLayout are used to create a pleasing appearance.
|
RadioOne.java
|
import java.awt.*;
import java.applet.*;
public class RadioOne extends Applet
{
public void init()
{
setLayout(new BorderLayout());
add("North", makeButtons());
}
public Panel makeButtons()
{
CheckboxGroup cbg = new CheckboxGroup();
Checkbox a = new Checkbox("Good", cbg, false);
Checkbox b = new Checkbox("Better", cbg, false);
Checkbox c = new Checkbox("Best", cbg, true);
Panel p = new Panel();
p.setLayout(new GridLayout(1, 0, 5, 5));
p.add(a);
p.add(b);
p.add(c);
Panel p2 = new Panel();
p2.add(p);
return p2;
}
}
|
Radio Events
Just as with regular Checkboxes, you respond to action events in Java 1.0 and ItemEvents in Java 1.1. If you don't want to respond to events, however, things are a little different. Because only one radio button can be selected at a time, the CheckboxGroup object keeps track of the selected item.
To find out which item is selected, you use:
| Checkbox selected = cbg.getSelectedCheckbox(); |
where cbg is your CheckboxGroup object. Remember, however, the CheckboxGroup doesn't fire any events. If you want to be notified when an event occurs you'll have to subscribe to the ItemEvents generated by each individual Checkbox.
Here's a final example for this lesson, RadioState.java, that draws one of three different ovals, depending upon which radio button is selected:
|
RadioState.java
|
import java.awt.*;
import java.applet.*;
import java.awt.event.*; // 1.1
public class RadioState extends Applet
implements ActionListener
{
CheckboxGroup cbg = new CheckboxGroup();
Checkbox good = new Checkbox("Good", false, cbg);
Checkbox better = new Checkbox("Better", false, cbg);
Checkbox best = new Checkbox("Best", true, cbg);
Button paintIt = new Button("Paint It");
public void init()
{
setLayout(new BorderLayout());
add("North", makeButtons());
add("South", paintIt);
paintIt.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
Graphics g = getGraphics();
int w = getSize().width;
int h = getSize().height;
int ratio = 1;
Checkbox current = cbg.getSelectedCheckbox();
if (current == good) ratio = 5;
else if (current == better) ratio = 3;
else if (current == best) ratio = 2;
g.clearRect(0, 0, w, h);
g.fillOval(w/2 - ((w/ratio)/2),
h/2 - ((h/ratio)/2),
w/ratio, h/ratio);
g.dispose();
}
public Panel makeButtons()
{
Panel p = new Panel();
p.setLayout(new GridLayout(1, 0, 5, 5));
p.add(good);
p.add(better);
p.add(best);
Panel p2 = new Panel();
p2.add(p);
return p2;
}
}
|
Something to Talk About
Here's something simple. Look at the partially completed code for the applet that appears here. How would you add the definitions for the fields a, b, c, and d, (as well as any other objects that are required), to get the results shown below?
[You don't need to worry about layout managers or anything of that sort.]
import java.awt.*;
import java.applet.*;
public class Wrapup12c extends Applet
{
// Add this stuff
public void init()
{
add(a);
add(b);
add(c);
add(d);
}
}
|
Please continue to the next section of this lesson.
|