2

I'm trying to implement a simple keylistener to make a graphic of an oval move with the left key arrow. The oval does not move nor even read the key press after testing with system.out.println. Any help would be appreciated.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class Game extends JFrame implements KeyListener{

  int x = 450;
  int y = 600;

  public Game() {
    setTitle("Game");
    setSize(1024, 768);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public void paint(Graphics g) {
    g.setColor(Color.BLACK);
    g.fillOval(x, y, 100, 100); 
  }

  public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_LEFT) {
      x = x + 20;
      System.out.println("works");
    }
  }
    public void keyReleased(KeyEvent e) {}
    public void keyTyped(KeyEvent e) {}


  public static void main(String[] args) {
    Game game = new Game();
  }
}
guarrana
  • 79
  • 1
  • 12
  • 3
    Just guessing: could it be that you have to call "addKeyListener(this)" on maybe your frame object? You see: making something a KeyListener ... doesn't automatically make the framework send key events to the listener. – GhostCat Mar 18 '16 at 21:23
  • This question is asked regularly. For example take a look at all the question found under the `"Related"` heading on the right side of this page. The answers you should concentrate on are the ones that recommend using `"Key Bindings"` which is the proper way to solve the problem. Also, you should NOT be doing custom painting in the paint() method of a JFrame. You should be overriding paintComponent() of a JPanel and then add the panel to the frame. See [Custom Paining](http://docs.oracle.com/javase/tutorial/uiswing/painting/index.html) for working examples. – camickr Mar 18 '16 at 21:25
  • Thank you Jägermeister, this fixed the issue. – guarrana Mar 18 '16 at 21:27

3 Answers3

3

You misunderstand the purpose and use of KeyListener. Your class implements that interface, but only implementations that are actually registered on the component that generates an event receive that event. That holds even when the component is itself a listener of the appropriate type. Perhaps, therefore, you want

game.addKeyListener(game);

Note also that you potentially have to deal with threading issues. To be properly synchronized, GUI initialization code generally needs to run on the EDT, as you can accomplish with the help of SwingUtilities.invokeAndWait() or SwingUtilities.invokeLater().

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
3

The oval does not move nor even read the key press after testing with system.out.println. Any help would be appreciated

As far as I see, you didn't add your listener, hence nothing happens when you press the key.

If you are adding to your current Game class, you can do this:

this.addKeyListener(this);

If you are adding the listener outside the current Game class, then:

gameInstance.addKeyListener(gameInstance);

Other issues with your codes:

  • You may want to use KeyBindings instead of KeyListener.
  • Do not override paint(g). Override paintComponent(g) instead. There is almost no reason for us to override paint(g).
  • Usually we do not create a customized JFrame. You may consider creating a JPanel (be it customized or not) and add it into your JFrame.
  • After adding the JPanel (a container) into your JFrame, you can pack() your frame and it will be able to determine its own preferredSize.
user3437460
  • 17,253
  • 15
  • 58
  • 106
  • @user3089040 You may want to take a look at my solution. – user3437460 Mar 18 '16 at 21:37
  • Very helpful, thanks. The JPanel helped with another issue I was having with repainting. – guarrana Mar 18 '16 at 21:39
  • @user3089040 Glad to help. – user3437460 Mar 18 '16 at 21:40
  • 2
    @user3089040: I see that you've accepted this answer, and good for you for doing this, but you also may wish to up-vote this answer as well as the other answer if you find them helpful. The general rule is to up-vote any answer that helps, and accept the answer that solves. Good luck. – Hovercraft Full Of Eels Mar 18 '16 at 21:42
  • @user3089040 `The JPanel helped with another issue I was having with repainting` - yes I mentioned that (and more) in my comment long before the "other issues" were added to this answer. You really should take the time to read all suggestions. – camickr Mar 19 '16 at 00:54
3

Let's start with the KeyListener issue. KeyListener is well know for not responding to key inputs, and will only generate KeyEvents when the component is focusable AND has focus.

Instead, you should be using the Key Bindings API

Next, you should avoid overriding paint of top level containers like JFrame, for more information why, have a look at

As a general rule of thumb, you should avoid extending JFrame at all and instead prefer using something like JPanel and override it's paintComponent method.

Also remember, painting in Swing is made up of a series of chained method calls, unless you really, really, really know what you're doing, you should always call the super paint method before performing any cusomt painting.

See Painting in AWT and Swing and Performing Custom Painting for more details

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366