I thought I would try and write a program that would paint a ball, and when the arrow keys are pressed, would move the ball around the screen in the direction pressed. First
Please do have a look at this code example :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintingPanel
{
private CustomPanel drawingArea;
private ActionMap actionMap;
private int x;
private int y;
private enum Direction
{
UP(KeyEvent.VK_UP),
DOWN(KeyEvent.VK_DOWN),
LEFT(KeyEvent.VK_LEFT),
RIGHT(KeyEvent.VK_RIGHT);
public int key;
private Direction(int key)
{
this.key = key;
}
public int getKey()
{
return key;
}
}
private class PanelAction extends AbstractAction
{
private Direction arrow;
public PanelAction(Direction a)
{
arrow = a;
}
@Override
public void actionPerformed(ActionEvent ae)
{
switch(arrow)
{
case UP:
y -= 1;
break;
case DOWN:
y += 1;
break;
case LEFT:
x -= 1;
break;
case RIGHT:
x += 1;
break;
}
drawingArea.setValues(x, y);
}
}
public PaintingPanel()
{
x = y = 5;
}
private void displayGUI()
{
JFrame frame = new JFrame("Painting Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingArea = new CustomPanel();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = drawingArea.getInputMap(condition);
actionMap = drawingArea.getActionMap();
for (Direction arrow : Direction.values())
{
int key = arrow.getKey();
String name = arrow.name();
inputMap.put(KeyStroke.getKeyStroke(
key, 0), name);
actionMap.put(name, new PanelAction(arrow));
}
frame.setContentPane(drawingArea);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PaintingPanel().displayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
private final int SIZE = 500;
private int x;
private int y;
private String text = "Hello World!";
public CustomPanel()
{
x = y = 5;
setOpaque(true);
setBackground(Color.WHITE);
}
public void setValues(int x, int y)
{
this.x = x;
this.y = y;
repaint();
}
@Override
public Dimension getPreferredSize()
{
return (new Dimension(SIZE, SIZE));
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GREEN.darker());
g.fillOval(x, y, 50, 50);
}
}
You can use the KeyboardFocusManager
to listen for keystrokes of the arrow keys and update the position of the ball. Here is the reworked code:
class BallFrame extends JFrame {
private static final int DEFAULT_WIDTH = 500;
private static final int DEFAULT_HEIGHT = 500;
final BallComponent ball = new BallComponent();
public BallFrame() {
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
super.setResizable(false);
super.add(ball);
super.setVisible(true);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP)
ball.move(0, -10);
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
ball.move(10, 0);
if (e.getKeyCode() == KeyEvent.VK_LEFT)
ball.move(-10, 0);
if (e.getKeyCode() == KeyEvent.VK_DOWN)
ball.move(0, 10);
return false;
}
});
}
}
And for BallComponent class:
static class BallComponent extends JComponent {
private double x = 225;
private double y = 225;
private Ellipse2D.Double ellipse = new Ellipse2D.Double(x, y, 50, 50);
public void move(int dX, int dY) {
x += dX;
y += dY;
ellipse = new Ellipse2D.Double(x, y, 50, 50);
repaint();
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.fill(ellipse);
}
}
It seems that you never initialized actionPress
- try adding this to your BallComponent constructor:
actionPress = new ActionPress();
ie, your constructor would look like this
public BallComponent()
{
super();
super.setFocusable(true);
InputMap imap1 = this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp1");
InputMap imap2 = this.getInputMap(JComponent.WHEN_FOCUSED);
imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp2");
InputMap imap3 = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp3");
actionPress = new ActionPress();
ActionMap amap = this.getActionMap();
amap.put("keyUp1", actionPress);
amap.put("keyUp2", actionPress);
amap.put("keyUp3", actionPress);
}