|
Java Take-Off Step Three: Applet basics. |
Here's a simple applet whose purpose is to draw:
import java.applet.*;
import java.awt.*;
import java.util.*;
public class ManyShapes extends Applet
{
// this method overrides the paint method from the Applet class
public void paint(
Graphics g // the Graphics context to draw with
)
{
// create a new number generator
Random r = new Random();
// draw 10000 shapes
for(int i = 0; i < 10000; i++)
{
// generate random values for our shape
int x = r.nextInt()%300;
int y = r.nextInt()%300;
int width = r.nextInt()%300;
int height = r.nextInt()%300;
// set a random color
g.setColor(new Color(r.nextInt()));
// generate a positive number between 0 and 4
int n = Math.abs(r.nextInt()%5);
// draw a shape based on the value of n
switch(n)
{
case(0):
g.draw3DRect(x, y, width, height, true);
break;
case(1):
g.drawRect(x, y, width, height);
break;
case(2):
g.drawOval(x, y, width, height);
break;
case(3):
g.fillRect(x, y, width, height);
break;
case(4):
g.fillOval(x, y, width, height);
break;
// this shouldn't happen; but if it does,
// print a message
default:
System.out.println("Invalid case: " + n);
break;
} // switch
} // for
} // paint
} // ManyShapes
Here's the HTML file:
<html>
<head>
<title>ManyShapes</title>
</head>
<body>
<hr>
<applet code=ManyShapes.class
width=300
height=300>
</applet>
<hr>
</body>
</html>
EXERCISES
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
// import java.util.*;
public class ButtonTest extends Applet implements ActionListener
{
// a single, lonely Button
private Button button;
// background colors used by the applet
private final Color bgColors[] = new Color[] {
Color.red, Color.blue, Color.green, Color.yellow
};
// index to the current background color
private int currentColor;
// this method overrides the init method from the Applet class
public void init()
{
// create a new Button object, register it with the applet, then add
// it to the applet
button = new Button("Press me!");
button.addActionListener(this);
add(button);
// initialize the index for background coloring
currentColor = -1;
changeWindowColor();
}
// this method overrides the paint method from the Applet class
public void paint(Graphics g)
{
// set the window's background color based on the current index
setBackground(bgColors[currentColor]);
// set the foreground (text) of the button to the background color
button.setForeground(bgColors[currentColor]);
} // paint
// increments the current background color index
private void changeWindowColor()
{
currentColor++;
if(currentColor == bgColors.length)
{
currentColor = 0;
}
}
// implementation of the actionPerformed method from the
// ActionListener interface
public void actionPerformed(ActionEvent e)
{
// if button fired the event, change the window's background color
if(button == e.getSource())
{
changeWindowColor();
repaint();
}
}
} // ButtonTest
The HTML for this applet is here:
<html>
<head>
<title>ButtonTest</title>
</head>
<body>
<hr>
<applet code=ButtonTest.class width=300 height=300></applet>
<hr>
</body>
</html>
Note that the HTML file keeps the same simple basic structure.
EXERCISES
Button show in a different color?
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class CheckboxTest extends Applet implements ItemListener
{
// a CheckboxGroup to hold a number of items
private CheckboxGroup cbg;
// selections used by the applet
private final String selections[] = {
"Pepsi", "Coke", "Mountain Dew", "Tab"
};
private Checkbox createCheckbox
(
String label, // label for Checkbox
CheckboxGroup group, // group Checkbox belongs to
boolean enabled // true to set set this Checkbox "on"
)
{
Checkbox cb = new Checkbox(label, group, enabled);
cb.addItemListener(this);
return cb;
}
// this method overrides the init method from the Applet class
public void init()
{
cbg = new CheckboxGroup();
for(int i = 0; i < selections.length; i++)
{
add(createCheckbox(selections[i], cbg, false));
}
}
// implementation of the itemStateChanged method from the ItemListener
// interface
public void itemStateChanged(ItemEvent e)
{
// print out a message about the selection
System.out.println("Yes, I certainly agree, " +
cbg.getSelectedCheckbox().getLabel() +
" is very delicious!");
}
} // CheckboxTest
EXERCISES
Here's another applet, and another GUI element:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ChoiceTest extends Applet implements ItemListener
{
// technical names of some skeletal bones
public final String[] BONES =
{ "foot", "leg", "knee", "hip", "rib", "shoulder", "neck" };
// a drop-down box containing the above String array
private Choice choice;
public void init()
{
setBackground(new Color(125, 0, 225));
// create our Choice and register it as an item listener
choice = new Choice();
for(int i = 0; i < BONES.length; i++)
{
// add a String to describe each choice
choice.add(BONES[i]);
}
choice.addItemListener(this);
add(choice);
}
// called when the state of a registered listener is changed
public void itemStateChanged(ItemEvent e)
{
// generate a different index than the one currently selected
int index;
do
{
index = (int)(Math.random()*BONES.length);
} while(index == choice.getSelectedIndex());
// print out an important fact about the human anatomy
System.out.println("The " + choice.getSelectedItem() +
" bone is connected to the " +
BONES[index] + " bone...");
}
} // ChoiceTest
EXERCISES
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
// allows the user to choose from several audio clips to play
public class AudioChoiceTest extends Applet implements ActionListener
{
// audio names for this program
public final String[] AUDIO =
{ "ping", "pop", "return", "salvation", "shuffle", "squish" };
// a drop-down box containing the above String array
private Choice choice;
// the actual audio clip data
private AudioClip[] clips;
// control buttons to play or stop sounds
private Button playClip;
private Button loopClip;
private Button stopClip;
private Button stopAllClips;
// tracks which clips are currently being played
private boolean[] clipsPlaying;
public void init()
{
setBackground(new Color(48, 255, 0));
// create the drop-down box and AudioClip objects
choice = new Choice();
clips = new AudioClip[AUDIO.length];
clipsPlaying = new boolean[AUDIO.length];
for(int i = 0; i < AUDIO.length; i++)
{
// add a String to describe each choice
choice.add(AUDIO[i]);
// add pathname and extension to the audio clip name
clips[i] = getAudioClip(getCodeBase(),
"audio/" + AUDIO[i] +".au");
// a value of false means that the clip is not playing
clipsPlaying[i] = false;
}
add(choice);
// create the buttons to play or stop audio clips
playClip = new Button("Play clip");
playClip.addActionListener(this);
add(playClip);
loopClip = new Button("Loop clip");
loopClip.addActionListener(this);
add(loopClip);
stopClip = new Button("Stop clip");
stopClip.addActionListener(this);
add(stopClip);
stopAllClips = new Button("Stop all clips");
stopAllClips.addActionListener(this);
add(stopAllClips);
// gray-out the stop buttons if there is nothing to stop
stopClip.setEnabled(false);
stopAllClips.setEnabled(false);
}
// stops all playing audio clips
public void stop()
{
for(int i = 0; i < AUDIO.length; i++)
{
if(clipsPlaying[i])
{
clips[i].stop();
}
}
}
// allows the user to play, loop, or stop the audio clips
public void actionPerformed(ActionEvent e)
{
int clipIndex = choice.getSelectedIndex();
AudioClip clip = clips[clipIndex];
// play the selected clip
if(e.getSource() == playClip)
{
clip.play();
stopClip.setEnabled(true);
stopAllClips.setEnabled(true);
clipsPlaying[clipIndex] = true;
}
// loop the selected clip
else if(e.getSource() == loopClip)
{
clip.loop();
stopClip.setEnabled(true);
stopAllClips.setEnabled(true);
clipsPlaying[clipIndex] = true;
}
// stop the selected clip
else if(e.getSource() == stopClip)
{
clip.stop();
stopClip.setEnabled(false);
stopAllClips.setEnabled(false);
clipsPlaying[clipIndex] = false;
// enable stop buttons if at least one clip is playing
for(int i = 0; i < AUDIO.length; i++)
{
if(clipsPlaying[i])
{
stopClip.setEnabled(true);
stopAllClips.setEnabled(true);
break;
}
}
}
// stop all playing clips
else if(e.getSource() == stopAllClips)
{
for(int i = 0; i < AUDIO.length; i++)
{
if(clipsPlaying[i])
{
clips[i].stop();
clipsPlaying[i] = false;
}
}
stopClip.setEnabled(false);
stopAllClips.setEnabled(false);
}
}
} // AudioChoiceTest
You will also need the following files:
These files should be placed where?
EXERCISES
CardLayout (please check the API).
import java.awt.*;
import java.applet.*;
public class CardTest extends Applet implements Runnable
{
// a Thread to act as the timer
private Thread timer;
public void init()
{
// create a new CardLayout
setLayout(new CardLayout());
// create 10 buttons stacked within the CardLayout
for(int i = 1; i <= 10; i++)
{
// the second parameter is a mandatory String representation
// of the Button to add
add(new Button("Card " + i), "Card " + i);
}
// register this applet as a Thread
timer = new Thread(this);
}
public void start()
{
timer.start();
}
public void stop()
{
timer = null;
}
// define the run method as prescribed in the Runnable interface
public void run()
{
CardLayout layout = (CardLayout)getLayout();
// get a reference to this thread
Thread t = Thread.currentThread();
// loop while the thread is active
while(t == timer)
{
layout.next(this);
// wait one second between updates
try
{
timer.sleep(1000);
}
catch(InterruptedException e) { return; }
}
} // run
} // CardTest
EXERCISES
import java.awt.*;
import java.applet.*;
public class PanelTest extends Applet
{
public void init()
{
// set the applet's layout to the default FlowLayout
setLayout(new FlowLayout());
// create a Panel with a 2x2 GridLayout and attach 4 buttons
// to it, then attach the panel to the parent applet
Panel p1 = new Panel();
p1.setLayout(new GridLayout(2, 2));
p1.add(new Button("B1"));
p1.add(new Button("B2"));
p1.add(new Button("B3"));
p1.add(new Button("B4"));
add(p1);
// create a second Panel with a BorderLayout and attach 5 buttons
// to it, then attach the panel to the applet
Panel p2 = new Panel();
p2.setLayout(new BorderLayout());
p2.add(new Button("North"), BorderLayout.NORTH);
p2.add(new Button("South"), BorderLayout.SOUTH);
p2.add(new Button("East"), BorderLayout.EAST);
p2.add(new Button("West"), BorderLayout.WEST);
p2.add(new Button("Center"), BorderLayout.CENTER);
add(p2);
} // init
} // PanelTest
EXERCISES
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
// allows an attribute value to be adjusted
class AttributeButton extends Button
{
// the Panel that owns this button
private AttributePanel parent;
public AttributeButton(String label, AttributePanel ap)
{
super(label);
parent = ap;
}
// updates the parent attribute's value
public int updatePanel(
int pointsRemaining // points left to allocate
)
{
// allocate a point for 'plus' buttons
if(getLabel().equals("+"))
{
// only allocate if there's points remaining
if(pointsRemaining > 0)
{
parent.allocatePoints(1);
return -1;
}
else return 0;
}
// otherwise, deallocate a point
else
{
// don't allow negative allocation
if(parent.getPointsAllocated() > 0)
{
parent.allocatePoints(-1);
return 1;
}
else return 0;
}
}
} // AttributeButton
// allows the value for single character Attribute to be adjusted
class AttributePanel extends Panel
{
// text description of the attribute
private String attribute;
// Label holding the points allocated to this attribute
private Label pointsAllocated;
public AttributePanel(String attr, ActionListener l)
{
attribute = attr;
pointsAllocated = new Label("0", Label.CENTER);
// set the panel layout within a 3x1 grid
setLayout(new GridLayout(3, 1));
setBackground(Color.green);
// add Labels to describe attribute
add(new Label(attr, Label.CENTER));
add(pointsAllocated);
// attach the +/- buttons to the parent ActionListner
Button incr = new AttributeButton("+", this);
incr.addActionListener(l);
Button decr = new AttributeButton("-", this);
decr.addActionListener(l);
// add another Panel with the plus/minus buttons
Panel p = new Panel();
p.add(incr);
p.add(decr);
add(p);
}
// updates the pointsAllocated label
public void allocatePoints(int n)
{
int value = getPointsAllocated() + n;
pointsAllocated.setText("" + value);
}
// returns the points allocated to this attribute
public int getPointsAllocated()
{
return Integer.parseInt(pointsAllocated.getText());
}
public String toString()
{
// return a verbose description of the attribute
return attribute + ": " + getPointsAllocated();
}
} // AttributePanel
public class AttributeTest extends Applet implements ActionListener
{
// overall points remaining to allocate
Label pointsRemaining;
// the attributes for this applet
private final String ATTRS[]
= { "Strength", "Wisdom", "Agility", "Magic" };
public void init()
{
pointsRemaining = new Label("Points remaining: 10", Label.CENTER);
// set the applet's layout to a FlowLayout
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 10));
// add the components to the layout
for(int i = 0; i < ATTRS.length; i++)
{
add(new AttributePanel(ATTRS[i], this));
}
add(pointsRemaining);
} // init
public void actionPerformed(ActionEvent e)
{
// get the points left to allocate
int n = Integer.parseInt(pointsRemaining.getText().substring(18));
// update the Button's Panel and the main Label
n += ((AttributeButton)e.getSource()).updatePanel(n);
pointsRemaining.setText("Points remaining: " + n);
}
} // AttributeTest
Can you figure out the purpose behind the program?
EXERCISES
Here's the HTML first:
<html>
<head>
<title>CharacterBuilder</title>
</head>
<body>
<hr>
<applet code=CharacterBuilder.class width=300 height=300>
<param name="SkillPoints" value="15">
</applet>
<hr>
</body>
</html>
And now the code:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
// the CharacterBuilder class consists of a number of Panels arranged within
// a CardLayout along with associated "back" and "next" buttons
public class CharacterBuilder extends Applet implements ActionListener
{
// selects the next and previous cards in cardPanel
private Button back;
private Button next;
private Panel attributePanel;
private SummaryPanel summaryPanel;
// final String arrays representing various attribute selections
private final String[] GENDERS = new String[] { "Male", "Female" };
private final String[] SKILLS = new String[]
{ "Strength", "Wisdom", "Agility", "Magic" };
private final String[] PROFESSIONS = new String[]
{ "Knight", "Ranger", "Archer", "Wizard", "Smith", "Druid" };
// this method overrides the init method from the Applet class
public void init()
{
// create a GridLayout to hold our Cards and Buttons
setLayout(new GridLayout(2, 1));
// get the number of skill points to be allocated to the character
int skillPoints;
try
{
skillPoints = Integer.parseInt(getParameter("SkillPoints"));
}
catch(NumberFormatException e)
{
skillPoints = 10;
}
// create an array of panels for our attributes; one for the name,
// gender, skills, and profession of the character
AttributePanel[] panels = new AttributePanel[] {
new TextFieldPanel("Name", "Enter your name: ", 20),
new CheckboxPanel("Gender", GENDERS, GENDERS[0]),
new SkillPanel("Skills", SKILLS, skillPoints),
new CheckboxPanel("Profession", PROFESSIONS, PROFESSIONS[0])
};
// create a Panel to place our CardLayout
attributePanel = new Panel();
attributePanel.setLayout(new CardLayout());
// add the AttributePanels to the main Panel
for(int i = 0; i < panels.length; i++)
{
attributePanel.add(panels[i], panels[i].getAttribute());
}
// create the SummaryPanel and add it to our CardLayout
summaryPanel = new SummaryPanel(panels);
attributePanel.add(summaryPanel, "Summary");
// add the attributePanel
add(attributePanel);
// create and add our "back" and "next" buttons
Panel p = new Panel();
back = new Button("back");
back.addActionListener(this);
p.add(back);
next = new Button("next");
next.addActionListener(this);
p.add(next);
p.setBackground(Color.white);
add(p);
}
// called when the "back" or "next" button is clicked
public void actionPerformed(ActionEvent e)
{
CardLayout cardLayout = (CardLayout)attributePanel.getLayout();
if(e.getSource() == back)
{
cardLayout.previous(attributePanel);
}
else if(e.getSource() == next)
{
cardLayout.next(attributePanel);
}
// update the Summary after each change
summaryPanel.update();
}
} // CharacterBuilder
import java.awt.*;
// Panel for holding character attributes
public abstract class AttributePanel extends Panel
{
// text description of the attribute
protected String attribute;
public AttributePanel(String attr)
{
attribute = attr;
}
public final String getAttribute()
{
return attribute;
}
// force subclasses to override the toString method
public abstract String toString();
} // AttributePanel
import java.awt.*;
// holds a String attribute within a Panel
public class TextFieldPanel extends AttributePanel
{
// the TextField for the attribute
private TextField textField;
public TextFieldPanel(String attr, String prompt, int textLength)
{
super(attr);
setLayout(new FlowLayout(FlowLayout.CENTER, 15, 0));
// add a Label if the prompt is a valid String
if(prompt != null)
{
add(new Label(prompt, Label.LEFT));
}
// create and add the TextField to the Panel
textField = new TextField(textLength);
add(textField);
}
public String toString()
{
// return the attribute, a "not specified" message
if(textField.getText().trim().equals(""))
{
return attribute + ": not specified";
}
return attribute + ": " + textField.getText().trim();
}
} // TextFieldPanel
import java.awt.*;
public class CheckboxPanel extends AttributePanel
{
// a CheckboxGroup to hold our Checkboxes
protected CheckboxGroup cbg;
// this method overrides the init method from the Applet class
public CheckboxPanel(String attr, String[] items, String selectedItem)
{
super(attr);
setLayout(new GridLayout(items.length+1, 1, 5, 5));
add(new Label(attribute, Label.CENTER));
// create the CheckboxGroup
cbg = new CheckboxGroup();
for(int i = 0; i < items.length; i++)
{
add(new Checkbox(items[i],
cbg,
items[i].equals(selectedItem)));
}
}
public String toString()
{
return attribute + ": " + cbg.getSelectedCheckbox().getLabel();
}
} // CheckboxPanel
import java.awt.*;
import java.awt.event.*;
// Represents a button capable of adjusting the value of a skill
class SkillButton extends Button
{
// Label referencing the points allocated to this skill
private Label pointsAllocated;
public SkillButton(String desc, Label label)
{
super(desc);
pointsAllocated = label;
}
// parses the value from the Label
public int getPointsAllocated()
{
return Integer.parseInt(pointsAllocated.getText());
}
// updates the pointsAllocated label
private void allocatePoints(int n)
{
int value = getPointsAllocated() + n;
pointsAllocated.setText("" + value);
}
// updates the parent attribute's value
public int update(
int pointsRemaining // overall points left to allocate
)
{
// allocate a point for 'plus' buttons
if(getLabel().equals("+"))
{
// only allocate if there's points remaining
if(pointsRemaining > 0)
{
allocatePoints(1);
return -1;
}
}
// otherwise, deallocate a point
else
{
// don't allow negative allocation
if(getPointsAllocated() > 0)
{
allocatePoints(-1);
return 1;
}
}
// de/allocation failed
return 0;
}
}
// holds numerical values for various character skills
public class SkillPanel extends AttributePanel implements ActionListener
{
// points allocated to each skill
Label[] pointsAllocated;
// overall points remaining to allocate
Label pointsRemaining;
// the attributes for this applet
private String[] skills;
public SkillPanel(String attr, String[] sk, int alloc)
{
super(attr);
skills = sk;
// create the pointsRemaining Label
pointsRemaining = new Label("Points remaining: " +
alloc,
Label.CENTER);
// set the applet's layout to a FlowLayout
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 10));
// add the components to the layout
pointsAllocated = new Label[skills.length];
for(int i = 0; i < skills.length; i++)
{
pointsAllocated[i] = new Label("0", Label.CENTER);
addSkill(skills[i], pointsAllocated[i]);
}
add(pointsRemaining);
}
private void addSkill(String skill, Label label)
{
Panel p = new Panel();
// set the panel layout within a 3x1 grid
p.setLayout(new GridLayout(3, 1));
p.setBackground(Color.green.darker());
// add Labels to describe attribute
p.add(new Label(skill, Label.CENTER));
p.add(label);
// attach the +/- buttons to the parent ActionListner
Button incr = new SkillButton("+", label);
incr.addActionListener(this);
Button decr = new SkillButton("-", label);
decr.addActionListener(this);
// add another Panel with the plus/minus buttons
Panel buttonPanel = new Panel();
buttonPanel.add(incr);
buttonPanel.add(decr);
p.add(buttonPanel);
add(p);
}
public String toString()
{
// return a String containing the allocation for each skill
String s = "";
int points = 0;
for(int i = 0; i < skills.length; i++)
{
points = Integer.parseInt(pointsAllocated[i].getText());
s = s + skills[i] + " (" + points + ") ";
}
return s;
}
public void actionPerformed(ActionEvent e)
{
// get the points left to allocate
int n = Integer.parseInt(pointsRemaining.getText().substring(18));
// update the Button's Panel and the main Label
n += ((SkillButton)e.getSource()).update(n);
pointsRemaining.setText("Points remaining: " + n);
}
} // SkillPanel
import java.awt.*;
// Panel containing a summary of the attributes
public class SummaryPanel extends Panel
{
// a Label to describe each attribute
private Label[] summaries;
// reference to array of AttributePanels for the attributes
private AttributePanel[] panels;
public SummaryPanel(AttributePanel[] ap)
{
super();
panels = ap;
setLayout(new GridLayout(panels.length+1, 1, 5, 5));
add(new Label("Summary:", Label.CENTER));
// add the Labels to the Panel
summaries = new Label[panels.length];
for(int i = 0; i < panels.length; i++)
{
summaries[i] = new Label("", Label.LEFT);
add(summaries[i]);
}
}
// since we don't know exactly which panel has been updated, let each
// AttributePanel update its Label
public void update()
{
for(int i = 0; i < panels.length; i++)
{
summaries[i].setText(panels[i].toString());
}
}
} // SummaryPanel
EXERCISES
A201/A597/I210/A348/A548/T540/NC009