4

I have literally no idea why my program isn't recognizing keyboard input. I have places print statements throughout the program to determine the issue, and I have determined that the keyPressed method never activates. This is for a game which I am making for a class project, and yes I am a relatively beginner programmer. Thanks in advance! (Code below)

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JApplet;


public class Dodger extends JApplet implements Runnable, KeyListener {

Thread myThread;

public Image bg;
public Image pic;
public boolean loaded;

public int cx, cy, speed, x, y;

public void init(){
    setSize(800,800);
    loaded = false;
    x = 2;
    y = 400;
    cx = 0;
    cy = 0;
    speed = 3;
    myThread = new Thread(this);
    myThread.start();
    addKeyListener(this);
}

public void run(){
    loadpic();
    repaint();
    while (myThread!=null)
    {

        try{
            myThread.sleep(18);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        repaint();
    }
}

public void upMotion(){
    cy = cy + speed;
}

public void downMotion(){
    cy = cy - speed;    
}

public void leftMotion(){
    cx = cx - speed;
}

public void rightMotion(){
    cx = cx + speed;
}

@Override
public void keyPressed(KeyEvent k) {

    if (k.getKeyCode() == KeyEvent.VK_LEFT) {
        System.out.println("work");
        leftMotion();
    }

    if (k.getKeyCode() == KeyEvent.VK_RIGHT) {
        rightMotion();
    }

    if (k.getKeyCode() == KeyEvent.VK_UP) {
        upMotion();
    }

    if (k.getKeyCode() == KeyEvent.VK_DOWN) {
        downMotion();
    }
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
}

public void loadpic(){
    bg = new ImageIcon(getClass().getResource("back.png")).getImage();
    pic = new ImageIcon(getClass().getResource("smile.png")).getImage();
    loaded = true;
    repaint();
}



public void paint(Graphics g){
    g.drawImage(bg, 0, 0, this);
    g.drawImage(pic, cx, cy, this);
}   
}
  • have you made sure that the applet has focus? Without the applet having focus key presses won't be captured. – ChadNC Jun 12 '12 at 14:59
  • For better help sooner, post an [SSCCE](http://sscce.org/). Note that I had to spend some moments working around the lack of images, before I could see the applet & test theories. – Andrew Thompson Jun 12 '12 at 15:13

3 Answers3

5

The key events are detected just fine when the applet is focusable & has focus. Managing focus has always been a problem with applets. The problem is mostly that Sun never bothered to specify the focus behavior that should ideally apply to a mixed page of focusable HTML elements and applet(s).

As per Tom's advice, add to the end of init()

setFocusable(true);

To be safe, also override:

public void start() {
    this.requestFocusInWindow();
}

As an aside, generally it is better to use key bindings in Swing. They also require the applet to have input focus.


Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
3

First off, you probably want to separate out your class from your KeyListener, as it makes it a bit harder to read.

Next, you want to get rid of the bare Thread and wrap it in a timer.

import javax.swing.Timer;

class Dodger extends JApplet {

    Timer imageUpdater; //replaces Thread

    /*...*/
    public void init() {
        /*etc*/
        loadpic();
        int repaintInterval = 100;
        imageUpdater = new Timer(repaintInterval,
            new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            }
        );
        imageUpdater.start();
        addKeyListener(new KeyHandler());
        setFocusable(true);
     }

    /*...*/
    private class KeyHandler extends KeyAdapter {
        /* Note that with this implementation, you do not have to override
         * unnecessary methods, as KeyAdapter is an abstract class that
         * implements all of the methods of KeyListener.
         */
        @Override
        public void keyPressed(KeyEvent e) {
        /*...*/
        }
    }
    /*...*/
}

Most of this is just code cleanup - the actual problem may be fixed (according to Tom, see comments) with the setFocusable(true).

Michael
  • 1,239
  • 9
  • 14
  • 2
    When it comes to the problem itself, setFocusable(true) in init() should do the trick. – toniedzwiedz Jun 12 '12 at 15:12
  • @Tom Strangely (to me) the applet is already focusable when launched using Eclipse. – Andrew Thompson Jun 12 '12 at 15:16
  • 1
    @AndrewThompson to me, it's not focusable. Launched using Netbeans 7.1.1 and Oracle JDK 1.7. To be honest, I've always found focusing applets a bit confusing. An extra call of setFocusable can't do any harm anyway. – toniedzwiedz Jun 12 '12 at 15:20
  • 1
    @Tom *"An extra call of setFocusable can't do any harm anyway."* You're right. I just tried it and that cured the 'no immediate focus' problem when running from Eclipse. *"I've always found focusing applets a bit confusing."* Tell me about it. See the lead-in to my (heavily edited) answer. – Andrew Thompson Jun 12 '12 at 15:23
1

I'm not really sure if it applies to Applets, but your Thread may not allowing the event dispatching to occur.

Try to run your "work" with SwingWorker.

PeterMmm
  • 24,152
  • 13
  • 73
  • 111
  • +1 for SwingWorkker, but maybe not, Thread is wrapped into Runnable, issue could be funny sleep at 18 miliseconds – mKorbel Jun 12 '12 at 15:26
  • @mKorbel I don't think `SwingWorker` is useful here. This is not a 'long running task' (drawing 2 images to an 800x800 viewing area), it is just a 'repetitive task' - just needs a `Timer`.. – Andrew Thompson Jun 12 '12 at 15:29
  • Anyway I think any thread that modifiers the GUI must run on Swing's event dispatch thread, as stated in SwingWorkers doc. It won't make any harm ... – PeterMmm Jun 12 '12 at 15:36
  • 1
    @PeterMmm after all discusions (with Andrew Thompson) [we can talking about](http://stackoverflow.com/questions/7940173/how-do-i-use-keyeventdispatcher/7940227#7940227) – mKorbel Jun 12 '12 at 15:39