0

I wrote some application and wanted to add some keyboard input to it. My main class extends a JPanel so i could add the keyAdapter into the constructor. The keyAdapter is a new class called "InputAdapter" extending keyadapter with it's keyPressed() and keyReleased() method. on click or release the console should print some string, e.g. here "Test"

I don't know why, but the console won't print any text. Also, when I tell it to turn a sprites visibility to false nothing happens as well.

So i guess the KeyAdapter isn't working properly, so could someone take a closer look into my codelines?

i guess this issue has nothing to do with the other implemented classes i wrote because when removing them, the issue with the non working keyboard input remains.

package com.ochs.game;

public class Game extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;

public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 3;

public boolean isRunning;

public Game() {
    addKeyListener(new InputAdapter());
    setFocusable(true);
    requestFocus();
    start();
}

public void start() {
    isRunning = true;
    new Thread(this).start();
}

public void stop() {
    isRunning = false;
}

public void run() {
    init();
    while(isRunning) {

        update();
        repaint();

        try {
            Thread.sleep(5);
        } catch (InterruptedException e) {
            System.out.println("Thread sleep failed.");
        }
    }
}

public void init() {

}

public void update() {

}

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D)g;

}

public static void main(String[] args) {
    Game gameComponent = new Game();
    Dimension size = new Dimension(WIDTH*SCALE, HEIGHT*SCALE);

    JFrame frame = new JFrame("Invaders");
    frame.setVisible(true);
    frame.setSize(size);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.add(gameComponent);
}
public class InputAdapter extends KeyAdapter {

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

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


}
}   
mKorbel
  • 109,525
  • 20
  • 134
  • 319
user2410644
  • 3,861
  • 6
  • 39
  • 59

3 Answers3

1

Your code works for me:

java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1ubuntu0.12.04.2)
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)

Tip 1 - You should override paintComponent(Graphics g) i guess, not paint()

public void paintComponent(Graphics g){

    super.paintComponent(g);
    //...
}

Tip 2 - Use addNotify() on your JPanel:

public void addNotify(){

    super.addNotify();
    //start from here
    new Thread(this).start();
}

Tip 3 - Launch your app this way, from the EDT Thread (see What does SwingUtilities.invokeLater do?)

SwingUtilities.invokeLater(new Runnable() {

    public void run(){

    //your code

   }
});

Hope it helps!

Community
  • 1
  • 1
Fernando
  • 7,785
  • 6
  • 49
  • 81
1

There are many possible reasons why this might not work. KeyListener is very fussy. It requires that the component that is registered to not only be focusable, but have focus.

Even though your component seems to both these things, if, for some reason, focus is grabbed by another component, the KeyListener will stop working.

You should use requestFocusInWindow and requestFocus is unreliable, but a better solution would be to use Key bindings, which has the ability to over come all that messiness with focus...

You should avoid overriding paint and use paintComponent instead, check out Performing Custom Painting for more details.

Mixing threads with Swing is tricky, you will also want to be sure that you are not violating the single thread rules of Swing when you are updating the your state. Check out Concurrency in Swing for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

Your basic code design is old AWT painting code. I echo everything MadProgrammer says for a better Swing design.

In addition:

  1. there is no need for an empty init() method. Get rid of the method and the call to the method.
  2. same for the update() method.

The big problem with the posted code is that you add the panel to the frame AFTER the frame is visible. You should always add components to the frame before making the frame visible:

JFrame frame = new JFrame("Invaders");
frame.add(gameComponent);
...
frame.setVisible(true);

Don't take the easy way out and just make the above change. Write code for a Swing program not an AWT program.

camickr
  • 321,443
  • 19
  • 166
  • 288