Handling Keyboard Events
Keyboard input works a lot like mouse input - a listener interface, an adapter class that saves you from writing empty methods, and an event object describing what happened. The one extra wrinkle with keyboards is focus: a component only receives key events while it actually has keyboard focus, and an applet doesn't get that for free.
KeyListener and KeyAdapter
java.awt.event.KeyListener declares three methods: keyTyped, keyPressed, and keyReleased. As with mouse listeners, KeyAdapter implements all three with empty bodies so you only override what you need:
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
// react to the key
}
});
keyPressed/keyReleased fire for any physical key, including non-printable ones
like arrows or Shift; keyTyped fires only for keys that produce an actual character. A
KeyEvent exposes both getKeyChar() (the character typed) and
getKeyCode() (a constant like KeyEvent.VK_LEFT for non-character keys).
Focus: setFocusable(true) and requestFocus()
An Applet is not focusable by default. Two calls are required before it will ever see a key
event:
| Call | What it does |
|---|---|
setFocusable(true) | Marks the component as eligible to receive keyboard focus at all. Call once, in init(). |
requestFocus() / requestFocusInWindow() | Actively asks the windowing system to hand focus to this component right now. |
Extending PaintApplet: Clear and Color-Pick Shortcuts
Add a KeyAdapter in init() that clears drawnPoints when
C is pressed, and sets currentColor directly when R, G,
or B is pressed. The existing cycleColor() method from the previous lesson stays
in the class as-is - it's simply not wired to a key here, though nothing stops a future lesson from
calling it:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.List;
public class PaintApplet extends Applet {
private Color currentColor = Color.BLUE;
private Font titleFont = new Font("Arial", Font.BOLD, 18);
private List<Point> drawnPoints = new ArrayList<>();
public void init() {
setBackground(Color.WHITE);
setFocusable(true);
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
drawnPoints.add(e.getPoint());
repaint();
}
});
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
char key = Character.toUpperCase(e.getKeyChar());
if (key == 'C') {
drawnPoints.clear();
} else if (key == 'R') {
currentColor = Color.RED;
} else if (key == 'G') {
currentColor = Color.GREEN;
} else if (key == 'B') {
currentColor = Color.BLUE;
}
repaint();
}
});
}
public void start() {
requestFocus();
}
public void paint(Graphics g) {
g.setFont(titleFont);
g.setColor(Color.BLACK);
g.drawString("Welcome to PaintApplet!", 20, 30);
g.drawRect(10, 10, getWidth() - 20, getHeight() - 20);
g.setColor(currentColor);
drawShapes(g);
g.setColor(currentColor);
for (Point p : drawnPoints) {
g.fillOval(p.x, p.y, 4, 4);
}
}
private void drawShapes(Graphics g) {
g.drawLine(20, 50, 120, 50);
g.drawRect(20, 60, 60, 40);
g.fillOval(100, 60, 40, 40);
int[] xPoints = {200, 230, 260};
int[] yPoints = {100, 60, 100};
g.drawPolygon(xPoints, yPoints, 3);
}
public void cycleColor() {
if (currentColor == Color.BLUE) currentColor = Color.RED;
else if (currentColor == Color.RED) currentColor = Color.GREEN;
else currentColor = Color.BLUE;
repaint();
}
}
Why requestFocus() Lives in start(), Not init()
setFocusable(true) is a one-time capability flag, so it belongs in init().
requestFocus() is different: it's an active request that only succeeds once the component is
actually showing on screen and attached to a window. When init() runs, the browser or
appletviewer may not have finished laying out and displaying the component yet, so a
requestFocus() call made there can silently fail depending on the implementation and timing.
start() runs right after the applet becomes visible, which is a much more reliable point to
ask for focus - and since start() can run again later (for example if the user navigates
away and back), focus gets re-requested each time that happens too.
PaintApplet so far has been hardcoded in the class itself.
Head to Applet Parameters to let the HTML page that embeds the applet
configure it from the outside.