PythonNerd
PythonNerd

Reputation: 57

keylistener is not responding to any keys?

I am trying to code a simple keyevent for a player movement script that would respond the the "w" key. I hope to eventually make it do something like move the character but for now im just trying to get it to respond. I am relatively new to java so please elaborate if you can. Also please note that the player will not be a text area when I actually get this working I just didnt want to display images and animations just yet. I have included a lot of comments to explain what i was trying to do on each line. Hope that helps! Here is my code so far:

import javax.swing.*; //importing swing for gui stuff
import java.awt.*; //importing awt for gui stuff
import java.awt.event.*; //importing awt event so i can add listeners

public class game { //creates the class

    static String player = "Player"; //initializes the variable for text i will put in the text area

    public static void main(String args[]) { //making a function (main) to run automatically and initialize the game

        JFrame f = new JFrame("Javax Swing UI"); //create frame for GUI
        GridLayout l = new GridLayout(2,4);
        f.setSize(300,300); //set the size of the frame in pixels x,y
        JTextArea t = new JTextArea(5,10); //create a text area to act as the player for the game (until i get an image working)
        t.append(player);
        t.setEditable(false); //make it so you cant edit the text area
        f.add(t);
        f.setLayout(l);
        f.setVisible(true); //load the frame and all objects inside it

    }

    public static void movement(JTextArea t) { //creating a method for moving my "character"
        t.addKeyListener(new KeyAdapter() { //adding key listener to my text area
            public void keyPressed(KeyEvent e) { //creating the method to respond to my key listener
                int key = e.getKeyCode(); //getting the key the user types
                if (key == KeyEvent.VK_W) { //checking if the key is "w"
                    System.out.println("if key == w !!! working"); //prints that the if statement is working
                }

            }

        });

    }

}

there is no error, it compiles fine, runs fine, but the keylistener is not responding to the "w" key. I assume it has something to do with the key code or my logic statements. I'll worry about the formatting later but as I said im just trying to get the keyevent to work. If someone more experienced in java could help that would be great! (I am using java 8).

EDIT [RESOLVED]: I have started coding out @DontKnowMuchButGetting Better's answer using KeyStrokes and I ran into this problem:

java:9: error: ';' expected
                       public void actionPerformed(ActionEvent e) {

java:9: error: ';' expected
                       public void actionPerformed(ActionEvent e) {
                                                                ^
2 errors

The code that throws the error looks a little like this:

public class move extends AbstractAction {

        public static void main(int right, int down) {

            int right = right;
            int down = down;

            @Override
            public void actionPerformed(ActionEvent e) {

                x += right * 4;
                y += down * 4;
                repaint();
            }

        }


    }

EDIT: resolved last edit, did some work on it and I am now getting these errors:

game.java:39: error: cannot find symbol
                String whenfocused = WHEN_IN_FOCUSED_WINDOW;
                                     ^
  symbol:   variable WHEN_IN_FOCUSED_WINDOW
  location: class game
game.java:40: error: cannot find symbol
                InputMap inputs = InputMap(whenfocused);
                                  ^
  symbol:   method InputMap(String)
  location: class game
game.java:41: error: cannot find symbol
                ActionMap actions = ActionMap();
                                    ^
  symbol:   method ActionMap()
  location: class game
game.java:44: error: Action is abstract; cannot be instantiated
                m = new Action();
                    ^
game.java:46: error: incompatible types: game.move cannot be converted to Action
                actions.put(key.toString(), m);
                                            ^
game.java:62: error: cannot find symbol
                        g.repaint();
                         ^
  symbol:   method repaint()
  location: variable g of type Graphics
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
6 errors

This is my new code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import java.applet.Applet;



public class game { //creates the class
    public static final int ph = 300;
    public static final int pw = 300;
    public final int w = 20;
    public final int h = 20;

    public int x = (pw - w) / 2;
    public int y = (ph - h) / 2;
    public void main(String args[]) { //making a function (main) to run automatically and initialize the game

        JFrame f = new JFrame("Javax Swing UI"); //create frame for GUI
        f.setSize(ph, pw); //set the size of the frame in pixels x,y
        f.setBackground(Color.WHITE);
        f.setVisible(true); //load the frame and all objects inside it

        KeyStroke left = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
        KeyStroke down = KeyStroke.getKeyStroke(KeyEvent.VK_S, 0);
        KeyStroke right = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0);
        KeyStroke up = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0);

        keyAdd(up, -1, 0);
        keyAdd(down, 0, 1);
        keyAdd(right, 1, 0);
        keyAdd(left, -1, 0);

    }

    public void keyAdd(KeyStroke key, int right, int down) {
        String whenfocused = WHEN_IN_FOCUSED_WINDOW;
        InputMap inputs = InputMap(whenfocused);
        ActionMap actions = ActionMap();

        move m = new move(right, down);
        m = new Action();
        inputs.put(key, key.toString());
        actions.put(key.toString(), m);
    }

    private class move {
        private int down;
        private int right;
        public move(int right, int down) {
            this.right = right;
            this.down = down;

        }

        public void actionPerformed(ActionEvent e, int down, int right, Graphics g) {

            x += right * 4;
            y += down * 4;
            g.repaint();
        }




    }



    protected void paintComponent(Graphics g,int x,int y,int w,int h, Color color) {
        g.setColor(color);
        g.fillRect(x, y, w, h);

    }


}









Upvotes: 1

Views: 539

Answers (1)

If you want to move a "player" based on a key-stroke having been pressed, then as per my comment to your original post, use Key Bindings, not a KeyListener. For one thing, Key Bindings can work even if the bound component does not have the focus, and this can be controlled by the condition int that you pass into the JComponent#getInputMap(...) method. In my example below, I pass in JComponent.WHEN_IN_FOCUSED_WINDOW which means that the bindings will respond if the component is in a window that has focus, even if the actual keyboard focus is on another component held by that window.

The Key Bindings tutorial can be found here: How to Use Key Bindings

Here is a demo program that moves a small red rectangle, my "sprite" based on the user's pressing an arrow key:

enter image description here

Please see code comments for more information on what this code is doing

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class MoveSomething extends JPanel {
    private static final int PANEL_WIDTH = 800;
    private static final int PANEL_HEIGHT = 600;
    private static final Color SPRITE_COLOR = Color.RED;
    private static final int SPRITE_W = 20;
    public static final int DELTA = 4;

    private int spriteX = (PANEL_WIDTH - SPRITE_W) / 2;
    private int spriteY = (PANEL_HEIGHT - SPRITE_W) / 2;

    public MoveSomething() {
        setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        setBackground(Color.WHITE);

        // keystrokes that the program will respond to
        // you can use the "w" key as well, simply via KeyEvent.VK_W
        KeyStroke upStroke = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
        KeyStroke downStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
        KeyStroke leftStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
        KeyStroke rightStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);

        // submit the key stroke for binding along with two int parameters
        // the right parameter that tells us if the key stroke should move things right (+1) or left (-1)
        // and the down parameter for moving sprite down (+1) or up (-1)
        submitKeyBinding(upStroke, 0, -1);
        submitKeyBinding(downStroke, 0, 1);
        submitKeyBinding(leftStroke, -1, 0);
        submitKeyBinding(rightStroke, 1, 0);
    }

    private void submitKeyBinding(KeyStroke keyStroke, int right, int down) {
        // set key bindings:
        int condition = WHEN_IN_FOCUSED_WINDOW;
        InputMap inputMap = getInputMap(condition);
        ActionMap actionMap = getActionMap();

        inputMap.put(keyStroke, keyStroke.toString());
        actionMap.put(keyStroke.toString(), new MoveAction(right, down));
    }

    // action used by the bindings to do the actual movement
    private class MoveAction extends AbstractAction {
        private int right;
        private int down;

        public MoveAction(int right, int down) {
            this.right = right;
            this.down = down;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            spriteX += right * DELTA;
            spriteY += down * DELTA;
            repaint(); // redraw the GUI
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(SPRITE_COLOR);
        g.fillRect(spriteX, spriteY, SPRITE_W, SPRITE_W);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        MoveSomething mainPanel = new MoveSomething();
        JFrame frame = new JFrame("MoveSomething");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

Upvotes: 1

Related Questions