1

I am trying to create a LinkedList of all the keys pressed, but the keyPressed() and keyReleased() methods aren't being called. I've already tried frame.setFocusable(true). Here is my code (also sorry if's a big pile of spaghetti):

Window.java

public class Window {
    protected JFrame frame;

    private boolean clicked = false; // TODO: Mouse input
    private LinkedList<Character> keysDown = new LinkedList<>();

    public Window(String title, Dimension resolution, Canvas display) {
        frame = new JFrame(title);
        Dimension decoratedResolution = new Dimension(resolution.width + 16, resolution.height + 38); // The resolution of the window is mismatched, this makes it so resolution.height is actually the bottom of the screen and not a little further below and the same for resolution.width.

        frame.setPreferredSize(decoratedResolution);
        frame.setMinimumSize(decoratedResolution);
        frame.setMaximumSize(decoratedResolution);
        frame.setResizable(false);

        frame.setLocationRelativeTo(null); // Center the window
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setFocusable(true);

        frame.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {}

            @Override
            public void keyPressed(KeyEvent e) {
                char character = e.getKeyChar();

                if (!keysDown.contains(character))
                    keysDown.add(character);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                char character = e.getKeyChar();
                
                keysDown.remove((Object)character);
            }
        });

        frame.add(display);
        frame.setVisible(true);
    }

    public boolean isMouseDown() {
        return clicked;
    }

    public Vector2 getMousePosition() {
        Point point = MouseInfo.getPointerInfo().getLocation();
        SwingUtilities.convertPointFromScreen(point, frame);

        return new Vector2(point);
    }

    public LinkedList<Character> getKeysDown() {
        return keysDown;
    }
}

Edit: All the other code relevant is below

P.S. This is one of my first times using stack overflow so If I made a mistake in formatting the question, let me know.

Game.java

public class Game extends Canvas implements Runnable {
    // General Settings
    public static final String TITLE = "Game";
    public static final Dimension RESOLUTION = new Dimension(800, 450);
    public static final int FPS = 60;

    // Do not modify
    protected static final long NANO_SECOND = 1000000000;

    public float timeScale = 1f;
    public volatile boolean running = false; // Set to false to stop the game

    public Thread thread;
    public Window window;
    public Renderer renderer;

    public static void main(String[] args) {
        new Game();
    }

    public Game() {
        start();
    }

    public void start() {
        init();
    }

    public void init() {
        window = new Window(TITLE, RESOLUTION, this);
    }

    public void run() {
        final float RENDER_INTERVAL = 1f / FPS;

        long then = System.nanoTime();
        long now = then;

        float deltaTime = 0f;

        int frames = 0;

        while (running) {
            now = System.nanoTime();
            deltaTime = (float)(now - then) / NANO_SECOND;

            update(deltaTime * timeScale);

            if (!running)
                break;

            then = now;
            Thread.onSpinWait();
        }
    }

    public void update(float deltaTime) {
        if (window.getKeysDown().contains('d'))
            System.out.println("d pressed");
    }
  • I see nothing wrong at first glance, but I can't see how you'd verify if the necessary changes are done, there doesn't seem to be any visual feedback. Could you [edit] it to turn that code into a [mre] that actually demonstrates the problem (i.e. add a `main` method and some output)? – Joachim Sauer Feb 08 '23 at 11:55
  • And, unrelated to your problem: `remove()` with a `char` will call `remove(int)` (i.e. remove an object by its index). You need to force the use of the Object version by using `remove((Object) char)`. Also, checking `contains` first is unnecessary, as `remove` will simply do nothing if it doesn't find the value. Is your Canvas passing through the key presses, or is it swallowing them? – Joachim Sauer Feb 08 '23 at 11:59
  • Oh, and I'm now remembering that one shouldn't mix plain AWT components and Swing. `Canvas` is an AWT component, you [shouldn't use it in a Swing application](https://stackoverflow.com/questions/776180/how-to-make-canvas-with-swing). – Joachim Sauer Feb 08 '23 at 12:03
  • `getKeyChar()` will *never* return a valid value for keyPressed or keyReleased events. It is only meaningful in keyTyped events. For keyPressed and keyReleased, you need to call `getKeyCode()`. All of this is well documented in [the KeyEvent documentation](https://docs.oracle.com/en/java/javase/19/docs/api/java.desktop/java/awt/event/KeyEvent.html). – VGR Feb 08 '23 at 15:13

1 Answers1

0

It turns out I had to call addKeyListener() in the Game class.