A little hard to tell from the code snippet, but, KeyListeners aren't very reliable. If the key stroke is been consumed (by the UI and underlying implementation) you may not be notified.
Try looking at InputMap and ActionMap instead.
InputMap im = getInputMap(JTable.WHEN_FOCUSED_COMPONENT);
ActionMap am = getActionMap();
KeyStroke downKey = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
KeyStroke upKey = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
im.put(downKey, "Action.down");
im.put(upKey, "Action.up");
am.put("Action.down", new DownAction());
am.put("Action.up", new UpAction());
And see where it takes you...
Update:
Ahh, it's so obvious now, you've overridden the x/y width/height methods of the panel expecting the layout manager to use them to layout out the component, but not really providing a layout manager who knows how to deal with it.
BorderLayout does not care about you "size" or "position" requirements, it will override them with what it thinks you component should be.
What you want to do is use an absolute layout manager instead (null). Also, you DON'T want to implement the X/Y, width/height management, as this is already taken care for you.
So.
In the Pong class. Change the layout manager from BorderLayout to null (also update the add(paddle) method to remove the BorderLayout reference, not required, but removes confusion).
In the Paddle class, remove all references to the x/y, width/height, you don't need them. Instead use setBounds/setLocation.
public class Paddle extends JPanel {
Paddle(){
this(0, 0, 20, 40);
}
Paddle(int x, int y, int width, int height){
setBounds(x, y, width, height);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
// The graphics context has already been translated to x/y for use,
// so we don't need to care about it
g.fillRect(0, 0, getWidth(), getHeight());
}
public void moveDown(){
setLocation(getX(), getY() + 3);
}
public void moveUp(){
setLocation(getX(), getY() - 3);
}
}
And viola, it works.