Java Keylistener Not Called

Keylistener not working for JPanel

If you search this problem, you'll see that it is asked and has been solved many times.

  • KeyListeners need to be on the focused component to work. One solution is to give your component the focus after first making it focusable.
  • Better by a long shot however is to use Key Bindings. Google the tutorial on this.

Please have a look at my answer to this question for more on this, including many of the gory details.

java keylistener not called

I'll bet that you're requesting focus before the JPanel has been rendered (before the top level window has either had pack() or setVisible(true) called), and if so, this won't work. Focus request will only be possibly granted after components have been rendered. Have you checked what your call to requestFocus() has returned? It must return true for your call to have any chance for a success. Also it's better to use requestFocusInWindow() rather than requestFocus().

But more importantly, you shouldn't be using KeyListeners for this but rather key bindings, a higher level concept that Swing itself uses to respond to key presses.

Edit
An example of an SSCCE:

import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

public class TestKeyListener extends JPanel {
private KeyLis listener;

public TestKeyListener() {
add(new JButton("Foo")); // something to draw off focus
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}

private class KeyLis extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
System.out.println("VK_LEFT pressed");
break;
case KeyEvent.VK_RIGHT:
System.out.println("VK_RIGHT pressed");
break;
}
}
}

private static void createAndShowGui() {
TestKeyListener mainPanel = new TestKeyListener();

JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Edit 2
And the equivalent SSCCE using Key Bindings:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class TestKeyBindings extends JPanel {

public TestKeyBindings() {
add(new JButton("Foo")); // something to draw off focus
setKeyBindings();
}

private void setKeyBindings() {
ActionMap actionMap = getActionMap();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition );

String vkLeft = "VK_LEFT";
String vkRight = "VK_RIGHT";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight);

actionMap.put(vkLeft, new KeyAction(vkLeft));
actionMap.put(vkRight, new KeyAction(vkRight));

}

@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}

private class KeyAction extends AbstractAction {
public KeyAction(String actionCommand) {
putValue(ACTION_COMMAND_KEY, actionCommand);
}

@Override
public void actionPerformed(ActionEvent actionEvt) {
System.out.println(actionEvt.getActionCommand() + " pressed");
}
}

private static void createAndShowGui() {
TestKeyBindings mainPanel = new TestKeyBindings();

JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Edit 3
Regarding your recent SSCCE, your while (true) loops are blocking your Swing event thread and may prevent user interaction or painting from happening. Better to use a Swing Timer rather than while (true). For example:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;

import javax.swing.*;

public class BbbTest extends JFrame {

private AreaOfGame areaOfGame;

public BbbTest() {
super("");
// setVisible(true);
this.setBackground(Color.darkGray);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setLayout(null);
setBounds(200, 10, 400, 700);

areaOfGame = new AreaOfGame();
this.add(areaOfGame);
setVisible(true);

startGame();
}

public int generateNext() {
Random r = new Random();
int n = r.nextInt(7);
return n;
}

public void startGame() {
// while (!areaOfGame.GameOver()) {
// areaOfGame.startGame(generateNext());
// }

areaOfGame.startGame(generateNext());
}

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

class AreaOfGame extends JPanel {

private static final int rightside = 370;

private int bottom;
private int top;

private int currentPos;
private int currentver;
private KeyLis listener;

public AreaOfGame() {
super();

bottom = 650;
top = 50;
setLayout(null);
setBounds(20, 50, 350, 600);
setVisible(true);

this.setBackground(Color.lightGray);

listener = new KeyLis();
this.setFocusable(true);
if (this.requestFocus(true))
System.out.println("true");
;
this.addKeyListener(listener);

currentPos = 150;
currentver = 0;
}

public void startGame(int n) {
// while (verticallyInBound()) {
// System.out.println("anything");
// }

int timeDelay = 50; // msecs delay
new Timer(timeDelay , new ActionListener() {

public void actionPerformed(ActionEvent arg0) {
System.out.println("anything");
}
}).start();

}

public boolean verticallyInBound() {
if (currentPos <= bottom - 50)
return true;
return false;
}

public boolean GameOver() {
if (top >= bottom) {
System.out.println("game over");
return true;
}

else
return false;
}

public boolean horizontalyInBounds() {
if (currentPos <= rightside && currentPos >= 20)
return true;
else
return false;
}

class KeyLis implements KeyListener {

@Override
public void keyPressed(KeyEvent e) {
System.out.println("called");
currentver += 5;
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (horizontalyInBounds())
currentPos -= 5;
break;
case KeyEvent.VK_RIGHT:
if (horizontalyInBounds())
currentPos += 5;
break;
}
repaint();

}

@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent e) {
System.out.println("called 3");
}
}
}
}

KeyListener not detecting key presses

There are a number of issues.

First, you're adding the KeyListener to the JFrame, the problem with that is, a JFrame is made of a number of other components...

JRootPane

The next problem is, the KeyListener will only respond to key events if:

  1. The component is focusable AND
  2. The component has keyboard focus

So, when you add other components to the UI, I'm assuming that Return and HideHint are actually JButtons, they can, and often do, steal focus rendering your KeyListener useless.

As is almost the case with KeyListener, the answer is, don't use it. No seriously. If you want more control over when a key event is triggered, then you should use the Key Bindings API which provides not only a more flexible and re-usable API, but provides you with control over how to configure the at what focus level a key event would be triggered

KeyListener not working in JPanel?

I think my program isn't receiving focus and that's the problem,

That is the usual problem when a KeyListener doesn't work.

 this.requestFocusInWindow();

The above statement only works if the GUI is currently visible. Since you are executing the statement in the panel constructor it will have no effect. A component must be displayed on a visible GUI in order for a component to request focus.

You must request focus AFTER the GUI is visible.

Or, another option is to use the RequestFocusListener .

Why are you use a KeyListener? Swing was designed to be used with KY Bindings.

KeyListener Not working/Not being called?

Another solution for this problem would be to make an instance in the main method for example:

KeyListener() listener = new Game_Main();

Then you can cut the line:

this.addKeyListener(this);

from the constructor and put it in the main method. After than change the first this to frame and the second this to listener, it will work just fine. You simply register or input the listener to the frame in order to execute the event.



Related Topics



Leave a reply



Submit