Charlie Harper
Charlie Harper

Reputation: 379

KeyListener active only after click on canvas

I have a class which implements KeyListener, all's working fine, but there a little problem that my KeyListener works only after I click on a Canvas, so if I start a game, I have to click once on it and then I can use my keyboard, code:

public class Game extends Canvas implements Runnable {
    ....
    initGame() {
        ...
        addKeyListener(new Keyboard());
        setFocusable(true);
    }

    private class Keyboard implements KeyListener {
        ...
    }
}

-is there a method which make my canvas "active" after creating?

Upvotes: 0

Views: 3906

Answers (3)

K1TS
K1TS

Reputation: 1

I solved this problem in the next way: I created Canvas object, added KeyListener to it and made this object focusable. After these operations I added Canvas object to JFrame and everything started working fine.

Upvotes: 0

Braj
Braj

Reputation: 46871

It might be an issue if Canvas is added after making JFrame visible.

Call

frame.setVisible(true)

in the end after adding all the components on it.

This is what happening with me if I add Canvas after making JFrame visible and I have to click on Canvas to gain focus on it.


-- EDIT --

Sample code to understand it (try after un-commenting last frame.setVisible(true))

import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class CanvasDemo extends Canvas implements ActionListener, KeyListener {

    public CanvasDemo() {
        addKeyListener(this);
        setFocusable(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setVisible(true);

        CanvasDemo apple = new CanvasDemo();            
        frame.add(apple);

        frame.setTitle("The Game");
        // frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    @Override
    // animates rectangle
    public void actionPerformed(ActionEvent arg0) {
        System.out.println("action performed");
    }

    @Override
    public void keyPressed(KeyEvent arg0) {
        System.out.println("key pressed");
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        System.out.println("key released");
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        System.out.println("key typed");
    }
}

Upvotes: 0

MadProgrammer
MadProgrammer

Reputation: 347314

KeyListener will only respond to key events when the component it is registered to is focusable AND has focus.

While you can use requestFocusInWindow, there is no guarantee that focus will be transferred to the component and if focus is lost for some reason (you click on another component), then you back to square one.

A better solution is to use a JComoponet based componet (like JPanel) and make use of the Key Bindings API which allows you to define the focus level that triggers the key events

Upvotes: 1

Related Questions