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...
The next problem is, the KeyListener
will only respond to key events if:
- The component is focusable AND
- The component has keyboard focus
So, when you add other components to the UI, I'm assuming that Return
and HideHint
are actually JButton
s, 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
What Is the Purpose of 'Class.Forname("My_Jdbc_Driver")'
Hexadecimal to Integer in Java
Difference Between Role and Grantedauthority in Spring Security
Programmatically Change Log Level in Log4J2
Can Constructor Return a Null Object
Deserialize JSON to Arraylist<Pojo> Using Jackson
How to Find the Console Width with Java
Java Error: "Your Security Settings Have Blocked a Local Application from Running"
Jfreechart with Selectable Domain Axis and Zoom
Spring Autowiring Class VS. Interface
What's in an Eclipse .Classpath/.Project File
(Unknown Source) in Exception Stack Trace
Arrayindexoutofboundsexception When Iterating Through All the Elements of an Array
How to Insert a Character in a String at a Certain Position
Java: Convert String to Timestamp
How to List All Classes Loaded in a Specific Class Loader
"The Public Type <<Classname>> Must Be Defined in Its Own File" Error in Eclipse