Solution for
Programming Exercise 6.2
THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to
the following exercise from this on-line
Java textbook.
Exercise 6.2:
Improve your dice applet from the previous exercise so that it also responds
to keyboard input. When the applet has the input focus, it should be hilited
with a colored border, and the dice should be rolled whenever the user
presses a key on the keyboard. This is in addition to rolling them when
the user clicks the mouse on the applet. Here is an applet that
solves this exercise:
Discussion
The modifications that have to be made to the program from
the previous exercise are fairly
straightforward. The applet has to handle key presses, so it must implement the
KeyListener interface, and it must register itself to
listen for key events by calling dice.addKeyListener(this) in
its init() method. (In fact it is actually the
drawing surface component, dice, that gets the input focus and generates key events.)
The keyPressed() method just
has to roll the dice, by calling the same roll() subroutine
that is used by the mousePressed() routine.
The border of the applet changes from blue to red when the applet
has the input focus.
In order to implement this, the applet must
process focus events. So it needs to implement the FocusListener
interface and register itself to listen for focus events from the dice component. A
boolean-valued instance variable, focused, is set to true
when the applet gains the focus and to false when the applet loses the
focus. The color that is used for drawing the border depends on the value
of this variable.
This processing of focus events is identical to what was
outlined in Section 6.5.
There is one thing that is easy to forget: ,
A JPanel does not automatically receive the input focus when the
user clicks on it. The focus must be requested by calling the
requestFocus() method. This is done in the mousePressed()
routine, in response to a mouse click on the applet. (If you forget this,
your applet might actually still work on some platforms, but on others it will never
get the input focus and the keyboard will never work.)
In the following solution, modifications to the solution for Exercise 6.1
are shown in red.
The Solution
/*
Shows a pair of dice that are rolled when the user clicks on the
applet or if the applet has the input focus and the user presses
any key. It is assumed that the applet is 100-by-100 pixels.
A clicking sound is played when the dice are rolled.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ClickableDice2 extends JApplet
implements MouseListener, FocusListener, KeyListener {
int die1 = 4; // The values shown on the dice.
int die2 = 3;
boolean focused; // This is true when the applet has the
// input focus. It's value is managed by
// the focusGained() and focusLost() methods.
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 use it as the applet's content pane.
// Set the applet to listen for events from the DiceCanvas,
// and set the background color of the DiceCanvas.
dice = new DiceCanvas();
setContentPane(dice);
dice.addMouseListener(this);
dice.addFocusListener(this);
dice.addKeyListener(this);
dice.setBackground( new Color(200,200,255) ); // light blue
}
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 focusGained(FocusEvent evt) {
// This is called when the dice canvas gets the input focus
focused = true; // Record the fact that we have focus.
dice.repaint(); // Redraw with a red border.
}
public void focusLost(FocusEvent evt) {
// This is called when the dice canvas loses the input focus
focused = false; // Record the fact that we don't have focus.
dice.repaint(); // Redraw with a blue border.
}
public void mousePressed(MouseEvent evt) {
// When the user clicks the applet, roll the dice.
// Also, request the input focus.
roll();
dice.requestFocus();
}
public void keyPressed(KeyEvent evt) {
// When the user presses any key (and the applet has
// the input focus), roll the dice.
roll();
}
public void mouseReleased(MouseEvent evt) { } // Required for the
public void mouseClicked(MouseEvent evt) { } // MouseListener
public void mouseEntered(MouseEvent evt) { } // interface.
public void mouseExited(MouseEvent evt) { }
public void keyReleased(KeyEvent evt) { } // Required for the
public void keyTyped(KeyEvent evt) { } // KeyListener interface.
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 border and then
// draws the two dice. The border is red when
// the applet has focus and is blue otherwise.
super.paintComponent(g); // fill with background color.
if (focused)
g.setColor( Color.red);
else
g.setColor( Color.blue );
g.drawRect(0,0,99,99);
g.drawRect(1,1,97,97);
drawDie(g, die1, 10, 10);
drawDie(g, die2, 55, 55);
}
}
} // end class ClickableDice2
[ Exercises
| Chapter Index
| Main Index
]