2

I'm trying to make a Pong game for my class, but my KeyListener won't fire to its respective methods. I've looked on various questions, but its solutions haven't done any good for me.

I have a class that extends JPanel, and in its constructor, I have the following methods:

public final class GamePanel 
    extends javax.swing.JPanel 
    implements ActionListener, KeyListener {

public GamePanel(MainWindow Parent, WelcomePanel Sister) {
    parent = Parent;
    sister = Sister;
    ball = new Ball(this);
    Player1 = new Paddle(this, "left", "user");
    Player2 = new Paddle(this, "right", "user");
    setVisible(true);
    Timer t = new Timer(60, this);
    t.start();
    addKeyListener(this);
    this.requestFocusInWindow();
    setFocusable(true);
}

public void keyPressed(KeyEvent event) {
    Player1.keyPressedEvent(event) // Get's KeyCode, puts it in a switch and moves 
                                   // the increment of the paddle accordingly.

Player1.keyPressedEvent(KeyEvent event):

public void keyPressedAction(KeyEvent event) {
    int code = event.getKeyCode();

    if (this.side.equals("left")) {

        switch (code) {
        case KeyEvent.VK_UP:
            this.yIncrement = 10;
            break;
        case KeyEvent.VK_DOWN:
            this.yIncrement = -10;
            break;
        case KeyEvent.VK_LEFT:
            this.xIncrement = -10;
            break;
        case KeyEvent.VK_RIGHT:
            this.xIncrement = 10;
            break;
        }
    }
    else if (this.side.equals("right")) {

        switch (code) {
        case KeyEvent.VK_W:
            this.yIncrement = 10;
            break;
        case KeyEvent.VK_S:
            this.yIncrement = -10;
            break;
        case KeyEvent.VK_A:
            this.xIncrement = -10;
            break;
        case KeyEvent.VK_D:
            this.xIncrement = 10;
            break;
        }
    }
}

Could the reason for the malfunctioning be some interference with the ActionListener? I'm quite new to Java, but having looked at the code of some of my friend's, there using this and having no problems. The issue is that the paddle's don't move at all.

Community
  • 1
  • 1
Zizouz212
  • 4,908
  • 5
  • 42
  • 66
  • Had you debugged and saw if the method is really not being called? Maybe your move logic is wrong. – Marcos Vasconcelos Apr 06 '15 at 21:00
  • I've set an initial value to the increments (25), but then pressing keys won't actually do anything, if that's considered debugging. :) – Zizouz212 Apr 06 '15 at 21:01
  • I've toggled breakpoints in eclipse, but nothing seems to go to the key listener methods. The action performed method gets fired, but none of the key methods. Do you know how to manually fire a KeyEvent? I'll see if it fires like that too. – Zizouz212 Apr 06 '15 at 21:03
  • Use the a Key Bindings API, it will solve all the issues related to KeyListener – MadProgrammer Apr 06 '15 at 21:53
  • You appear to be implementing ActionListener but aren't fulfilling the contractural requirements of the interface, by implementation the actionPerformed method – MadProgrammer Apr 06 '15 at 22:08
  • @MadProgrammer Key Bindings API? And how am I not fulfilling the requirements of the interface? – Zizouz212 Apr 06 '15 at 22:25
  • [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html); You're not implementing the `actionPerformed` method, see [How to Write an Action Listeners](http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html) – MadProgrammer Apr 06 '15 at 22:35
  • Oh! I did implement the `actionPerformed` method, as well as the `keyTyped`, `keyPressed` and `KeyReleased` methods. I just listed one to show that I was calling other methods in other classes from within the implemented methods. – Zizouz212 Apr 07 '15 at 02:20
  • Just to be sure, add @Override to your implementation methods so you know you are implementing the correct ones. – Marcos Vasconcelos Apr 07 '15 at 16:49
  • Good Point, I think I forgot to add that in the question, but in my code I do. Phew! :) – Zizouz212 Apr 07 '15 at 21:26

2 Answers2

0

So, I figured out the issue. You have to make sure that you add your KeyListener inside your JFrame, and not your JPanel. I'm not completely sure if this has to do with the fact that I extend JFrame in another class, but adding the KeyListener to the JPanel does not work (through the implements nor through adding it explicitly). As a result, you need to the KeyListener to the JFrame that holds the JPanel. I'm not entirely sure why I need to do this (my friends' games don't need this), but it's a fix.

Inside my GamePanel, I have a reference to the JFrame that holds the GamePanel (given as parameter to its constructor).

public class GamePanel {

    public GamePanel(GamePanel Parent, WelcomePanel Sister) {
        this.parent = Parent; // Parent JFrame
        this.sister = Sister; // Sister JPanel that works with this JPanel

        this.parent.addKeyListener(this); // do this

Do the above, instead of:

public GamePanel(GamePanel Parent, WelcomePanel Sister) {
      addKeyListener(this);

This solved my issue. Thanks to all that helped! :)

Zizouz212
  • 4,908
  • 5
  • 42
  • 66
  • 1
    The panel just needs to be focusable and it will work. – Obicere Apr 07 '15 at 21:41
  • @Obicere If you bothered to take the time to look at the question, perhaps you'll notice that I have already tried that... – Zizouz212 Apr 07 '15 at 21:43
  • 1
    Yep, but it failed. You can test this as `setFocusableInWindow()` returns a boolean and will return false. You have to call them in the other order. – Obicere Apr 07 '15 at 21:45
  • @Obicere And How would you know that it failed? – Zizouz212 Apr 07 '15 at 21:45
  • 1
    Because if it succeeded this question wouldn't have been posted. – Obicere Apr 07 '15 at 21:45
  • I'll try it with the original code then. And there's no such applicable method. And the nearest methods `setFocusable()` and `setFocusableWindowState()` are void methods. – Zizouz212 Apr 07 '15 at 21:46
  • And voila. `setFocusable` doesn't make a difference. – Zizouz212 Apr 07 '15 at 21:54
  • 1
    Your panel is not visible at the time of adding. `This component must be displayable, focusable, visible and all of its ancestors (with the exception of the top-level Window) must be visible for the request to be granted.` The documentation makes it very clear as to how this should be done. – Obicere Apr 07 '15 at 21:55
  • If you have a solution, I welcome you to post an answer, perhaps helping me understanding what I need to do. – Zizouz212 Apr 07 '15 at 21:56
0

KeyListener is a poor choice in Swing and is natrious for having focus related issues (this is the way it's designed and not a bug). Instead you should be using Key Bindings which allows you to control the focus level at which a component will trigger key events

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks for the answer. I'm just going to let you know that this was for school (I'm in Grade 10) and I'm supposed to use the KeyListener interface. – Zizouz212 Jul 20 '15 at 13:36
  • Then tell you're school that `KeyListener` doesn't work and the Key Bindings API was introduced in Java 1.4 (back in 2001~) to overcome it's limitations and that they should move out of the dark ages ;) – MadProgrammer Jul 20 '15 at 21:31
  • Lol, okay. I would do that, but my school just got rid of the computer science department this year ;( – Zizouz212 Jul 20 '15 at 21:33