2

So I got 2 classes called Viewer and PaintWindow. In my case, the Viewer class acts as an controller while I use my PaintWindow class to paint things on a JPanel.

Now I'm trying to put together a little game but I don't understand how to implement the KeyListener to be able to control the game. What I want is a listener listeing for a keyEvent to happen so I can decide what will happen. This is how my code looks like:

Viewer:

public void run() {
    System.out.println("Viewer Run");
    cloud1 = new ImageIcon("src/images/cloud.png");
    cloud2 = new ImageIcon("src/images/cloud.png");
    background1 = new ImageIcon("src/images/background.png");
    playerStill = new ImageIcon("src/images/still.png");
    playerRight = new ImageIcon("src/images/right.png");
    playerLeft = new ImageIcon("src/images/left.png");


    paintWindow = new PaintWindow(background1); 
    paintWindow.showImage(playerStill, 30, 370);
    paintWindow.addKeyListener(new KeyTimerListener());
    paintWindow.startAlarm();



}
/*
 * Lyssnar på vad som händer när man trycker en viss knapp
 */
private class KeyTimerListener implements KeyListener {

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if(keyCode == 37){
             System.out.print("Left");
         }
        else if (keyCode == 39){
             System.out.print("Right");
        }
        else if (keyCode == 32 ){
             System.out.print("JUMP");
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
}

}

This is a part from my PaintWindow class:

    public void addKeyListener(KeyListener listener){
    this.listener.add(listener);
}
private class AT extends Thread {
    KeyEvent keyevent;
    public void run() {
        try {
            Thread.sleep(1);
        }catch(InterruptedException e) {

        }
        for(KeyListener al : listener) {
            al.keyPressed(keyevent);//<-----------------------------
            }
        thread = null;
    }
}


public void startAlarm() {
    if(thread==null) {
        thread = new AT();
        thread.start();
    }
}

I get a nullpointer exception as my KeyEvent is null. Sure I could define it as being a specific key, but that doesn't really help me here.

What have I missed?

Essej
  • 892
  • 6
  • 18
  • 33
  • What kind of _Component_ is PaintWindow ? – Arnaud Feb 11 '16 at 10:13
  • @Berger What do you mean? PaintWindow is just a class that creates a frame and JPanel and paints on it with the help of Graphics objects. – Essej Feb 11 '16 at 10:16
  • A custom Object does not receive any key events, _java.awt.Component_ does, or you may register a global listener , see : http://stackoverflow.com/questions/5344823/how-can-i-listen-for-key-presses-within-java-swing-across-all-components – Arnaud Feb 11 '16 at 10:21

2 Answers2

1

Forget about your KeyListener , since PaintWindow will receive no key event , not being a java.awt.Component .

Instead, add this code in your run() method :

KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher(new KeyEventDispatcher() {
                    @Override
                    public boolean dispatchKeyEvent(final KeyEvent e) {

                        // we only want PRESSED events  
                        if(e.getID() == KeyEvent.KEY_PRESSED){


                            int keyCode = e.getKeyCode();
                            if(keyCode == 37){
                                 System.out.print("Left");
                             }
                            else if (keyCode == 39){
                                 System.out.print("Right");
                            }
                            else if (keyCode == 32 ){
                                 System.out.print("JUMP");
                            }
                        }
                        return false;
                    }
                });

This will listen to all key events in your application.

More information in this topic :

How can I listen for key presses (within Java Swing) across all components?

Community
  • 1
  • 1
Arnaud
  • 17,229
  • 3
  • 31
  • 44
  • It worked, thanks. Is this a common practice that should be used? I have used ActionListeners quite alot before and recently learned how to use callback and observers, but these methods ain't something that can be used when I want keyPressed if the component itself isn't a java.awt.Component. I assume that JPanels is such a component, so that why it has worked for me before when I had classes extending JPanel? – Essej Feb 11 '16 at 10:58
  • Yes JPanel is a Component, so no problem in this case. If your object is not able to receive events, you have to listen at a higher level with KeyboardFocusManager , which _is responsible for managing the active and focused Windows_ , along as focus and event dispatching for all the components. I honestly couldn't tell if there is more common practice than this one, when KeyListener can't be used . – Arnaud Feb 11 '16 at 11:07
0

I think that your problem is that your not passing any key Listener. Try to instantiate your KeyTimerListener and add it. public void addKeyListener(new KeyTimerListener ()){ this.listener.add(listener);

user2656851
  • 1,643
  • 4
  • 12
  • 15