Search code examples
javaswingawtkeylistener

How to make the KeyListener functional?


I am learning java, and trying to create a little pong game just as a little test for me, but I can't make the keys right/left arrows work in my code, and I followed some tutorials but still not working.

My enemy and ball from de game works just fine, everything has collision, but still I can't make the controls/keys work.

Here is the code I'm using and my class Player (I think the mistake is somewhere here but I still don't know how to find it).

Code

public void keyPressed(KeyEvent e) {    
        if(e.getKeyCode() == KeyEvent.VK_RIGHT)
            player.right = true;        
        
            else if(e.getKeyCode() == KeyEvent.VK_LEFT)
                player.left = true;
    }

    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_RIGHT)
            player.right = false;
        
            else if(e.getKeyCode() == KeyEvent.VK_LEFT)
                player.left = false;
    } 

Class "Player"

public class Player {

    public boolean right,left;
    public int x,y;
    public int width,height;
    
    public Player(int x, int y) {
        this.x = x;
        this.y = y;
        this.width = 40;
        this.height = 10;
    }
    
    public void tick() {
        if(right) {
            x++;
        }
        else if(left) {
            x--;
        }
        if(x+width > Game.WIDTH) {
            x = Game.WIDTH - width;
        }
        else if(x < 0) {
            x = 0;
        }
    }

    public void Render(Graphics g) {
        g.setColor(Color.blue);
        g.fillRect(x, y, width,height);
    }
}

Solution

  • This small example has a KeyListener that works. The player doesn't move, because the Player.tick method is not called.

    // Pong.java
    
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import javax.swing.WindowConstants;
    
    public class Pong {
        public static void main(String[] arguments) {
            SwingUtilities.invokeLater(() -> new Pong().createAndLaunchGui());
        }
    
        private void createAndLaunchGui() {
            JFrame frame = new JFrame("Pong");
            frame.setBounds(240, 160, Game.WIDTH, Game.HEIGHT);
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frame.setContentPane(new Game());
            frame.setVisible(true);
        }
    }
    
    
    // Game.java
    
    import java.awt.Graphics;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import javax.swing.JPanel;
    
    public class Game extends JPanel {
        public static int WIDTH = 800;
        public static int HEIGHT = 600;
    
        private final Player player = new Player(400, 300);
    
        public Game() {
            setFocusable(true);
    
            addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent keyEvent) {
                    System.out.println("Game.keyPressed -- event: " + keyEvent);
    
                    if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
                        player.right = true;
                    } else if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
                        player.left = true;
                    }
                }
    
                @Override
                public void keyReleased(KeyEvent keyEvent) {
                    System.out.println("Game.keyReleased -- event: " + keyEvent);
    
                    player.right = false;
                    player.left = false;
                }
            });
        }
    
        @Override
        protected void paintComponent(Graphics graphics) {
            super.paintComponent(graphics);
    
            player.render(graphics);
        }
    }
    

    The key to solving your problem might be the call to the setFocusable(true) method in the constructor of the Game class. As explained in this Stack Overflow answer, events are only dispatched to the component that has focus. See that answer for more details and a link to a blog post with an extensive explanation.