Solution for
Programming Exercise 6.3
THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to
the following exercise from this on-line
Java textbook.
Exercise 6.3:
In Exercise 6.1, above, you wrote a pair-of-dice applet where the dice
are rolled when the clicks on the applet. Now make a pair-of-dice applet
that uses the methods discussed in Section 6.6.
Draw the dice on a JPanel, and place a "Roll" button
at the bottom of the applet. The dice should be rolled when the user clicks the
Roll button. Your applet should look and work like this one:
(Note: Since there was only one button in this applet, I added it directly
to the applet's content pane, rather than putting it in a "buttonBar" panel and adding
the panel to the content pane.)
Discussion
In the applets from Exercise 6.1 and Exercise 6.2,
a dice canvas filled the whole applet, and the applet responded directly
to mouse clicks on the dice canvas. For this version of the dice applet,
the user rolls the dice by clicking on a button. It does not respond to
clicks on the dice canvas. In this applet, there are two components:
the dice canvas and the button. The button is
an object of type JButton,
while the dice canvas is an object belonging to a nested class
named DiceCanvas that is almost the same as the DiceCanvas
class in Exercise 6.1.
In outline, the structure of this applet is similar to
HelloWorldJApplet.java
from Section 6.6. The init() method
creates the two components and adds them to the content pane of
the applet. The button is added to the content pane with
the command
getContentPane().add(button, BorderLayout.SOUTH);
The constant BorderLayout.SOUTH specifies that the
button goes at the bottom of the applet.
The position of the dice canvas in the content pane is specified
by the constant BorderLayout.CENTER:
getContentPane().add(dice, BorderLayout.CENTER);
This means that the dice canvas will occupy all the space in the
applet that is not occupied by the button.
In order to respond when the user presses the button, some object must listen for
ActionEvents from the button. As usual, any object can do this. In
my solution, the applet does the listening (although an anonymous class might be
more attractive). The applet
class implements the ActionListener interface, defines
an actionPerformed method that rolls the dice, and
registers itself to listen for ActionEvents from the
button.
I made one small change in the paintComponent() method that
draws the dice canvas. In the solution to Exercise 6.1, I assumed that
the size of the canvas was 100-by-100. Now, however, I don't know exactly
how big the button is, so I don't know exactly how tall the canvas will
be. To allow for variations in the size, the paintComponent()
method uses the getSize() method to get the actual size of
the canvas. This information is used to draw the two-pixel border around the
canvas:
g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
g.drawRect(1, 1, getSize().width - 3, getSize().height - 3);
The Solution
/*
Shows a pair of dice that are rolled when the user clicks on a
button It is assumed that the applet is 100 pixels wide. The
height of the applet should be more than 100 pixels, to allow
space for the button. A clicking sound is played when the dice
are rolled.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DiceWithButton extends JApplet implements ActionListener {
int die1 = 4; // The values shown on the dice.
int die2 = 3;
DiceCanvas dice; // An object belonging to the nested class
// DiceCanvas, which is used as the drawing
// surface on which the dice are displayed.
public void init() {
// To initialize the applet, create the drawing surface
// object and add it to the applet's content pane.
// Also create a button and add it to the content pane.
// Set the applet to listen for events from the button.
// And set the background color of the DiceCanvas.
dice = new DiceCanvas();
getContentPane().add(dice, BorderLayout.CENTER);
dice.setBackground( new Color(200,200,255) ); // light blue
JButton button = new JButton("Roll!");
button.addActionListener(this);
getContentPane().add(button, BorderLayout.SOUTH);
} // end init();
void drawDie(Graphics g, int val, int x, int y) {
// Draw a die with upper left corner at (x,y). The die is
// 35 by 35 pixels in size. The val parameter gives the
// value showing on the die (that is, the number of dots).
g.setColor(Color.white);
g.fillRect(x, y, 35, 35);
g.setColor(Color.black);
g.drawRect(x, y, 34, 34);
if (val > 1) // upper left dot
g.fillOval(x+3, y+3, 9, 9);
if (val > 3) // upper right dot
g.fillOval(x+23, y+3, 9, 9);
if (val == 6) // middle left dot
g.fillOval(x+3, y+13, 9, 9);
if (val % 2 == 1) // middle dot (for odd-numbered val's)
g.fillOval(x+13, y+13, 9, 9);
if (val == 6) // middle right dot
g.fillOval(x+23, y+13, 9, 9);
if (val > 3) // bottom left dot
g.fillOval(x+3, y+23, 9, 9);
if (val > 1) // bottom right dot
g.fillOval(x+23, y+23, 9,9);
}
void roll() {
// Roll the dice by randomizing their values. Tell the
// system to repaint the applet, to show the new values.
// Also, play a clicking sound to give the user more feedback.
die1 = (int)(Math.random()*6) + 1;
die2 = (int)(Math.random()*6) + 1;
play(getCodeBase(), "click.au");
dice.repaint();
}
public void actionPerformed(ActionEvent evt) {
// This will be called by the system when the user
// clicks the button. Respond by rolling the dice.
roll();
}
class DiceCanvas extends JPanel {
// A nested class to represent the drawing surface
// on which the dice are displayed.
public void paintComponent(Graphics g) {
// The paint method draws a blue border and then
// draws the two dice.
super.paintComponent(g); // fill with background color.
g.setColor( Color.blue );
g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
g.drawRect(1, 1, getSize().width - 3, getSize().height - 3);
drawDie(g, die1, 10, 10);
drawDie(g, die2, 55, 55);
}
}
} // end class DiceWithButton
[ Exercises
| Chapter Index
| Main Index
]