An ‘Etch-a-Sketch’ Program
Here’s an example of a program that uses keyboard input to produce a kind of ‘Etch-a-Sketch’ effect:
package swingExamples;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
class SketcherPanel extends JPanel
{
public SketcherPanel()
{
m_last = new Point2D.Double(100, 100);
m_lines = new ArrayList<Line2D> ();
// Add a key listener to listen for keystrokes
addKeyListener( new KeyHandler() );
// Allow focus to be set for the JPanel,
// to allow it to receive key events.
setFocusable(true);
}
/**
* paintComponent controls what is drawn on the panel
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// Draw all lines
for (Line2D line : m_lines)
{
g2.draw(line);
}
}
/**
* Add a new line segment to the Sketcher
* @param dx the movement in x direction
* @param dy the movement in y direction
*/
private void add(int dx, int dy)
{
// Compute end point
Point2D end = new Point2D.Double(m_last.getX() + dx,
m_last.getY() + dy);
// Add line segment
Line2D line = new Line2D.Double(m_last, end);
m_lines.add(line);
repaint();
// Remember new end point
m_last = end;
}
//// Private data ////
private Point2D m_last; // The last point entered
// Array to hold lines between successive points.
private ArrayList<Line2D> m_lines;
// Drawing increments ("slow" and "fast")
private static final int SMALL_INCREMENT = 1;
private static final int LARGE_INCREMENT = 5;
////// Inner classes //////
/**
* This is the class that listens for keystrokes
* in the SketcherPanel.
*/
private class KeyHandler implements KeyListener
{
public void keyPressed(KeyEvent event)
{
int keyCode = event.getKeyCode();
// Set distance
int d;
if (event.isShiftDown())
d = LARGE_INCREMENT;
else
d = SMALL_INCREMENT;
// Add line segment
if (keyCode == KeyEvent.VK_LEFT)
add( -d, 0);
else if (keyCode == KeyEvent.VK_RIGHT)
add(d, 0);
else if (keyCode == KeyEvent.VK_UP)
add(0, -d);
else if (keyCode == KeyEvent.VK_DOWN)
add(0, d);
}
public void keyTyped(KeyEvent event)
{
char keyChar = event.getKeyChar();
// Set distance
int d;
if (Character.isUpperCase(keyChar))
{
d = LARGE_INCREMENT;
keyChar = Character.toLowerCase(keyChar);
}
else
{
d = SMALL_INCREMENT;
}
// Add line segment
if (keyChar == 'h')
add( -d, 0);
else if (keyChar == 'l')
add(d, 0);
else if (keyChar == 'k')
add(0, -d);
else if (keyChar == 'j')
add(0, d);
}
// Unused KeyListener method
public void keyReleased(KeyEvent event)
{}
}
}
class SketcherFrame extends JFrame
{
public SketcherFrame()
{
setTitle("Sketch");
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container contentPane = getContentPane();
contentPane.add( new SketcherPanel() );
}
}
public class Sketcher
{
public static void main(String[] args)
{
SketcherFrame frame = new SketcherFrame();
frame.setVisible(true);
}
}
and here’s what it produces:

If you type left, right, up, or down arrow, the line draws in the appropriate direction. Similarly, if you type an ‘h’. ‘j’, ‘k’, or ‘l’ (that’s a lowercase ‘L’), the line will move similarly.
Note that the line moves 5 times faster if you use the Shift key in combination with the other key.
This program does retain information about the drawing: each successive point causes a line to be entered into the array, and the set of lines is used to [re]draw the lines on the panel, even when you iconify and restore the window.
