Keylistener Not Working for JPAnel

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.

JPanel key listener not working

Your setting you focus to your frame rather than the JPanel, But even changing the focus to the JPanel will provide a level of unpredictable behavior because it is really easy to lose focus of the JPanel. I suggest you use Key Binding or Change your keylistner method and other override methods to attach to the JFrame rather than the JPanel to assure focus is kept during use of application.

JPanel doesn't response to KeyListener event

Did you set that KeyListener for your HelloWorld panel would be that panel itself? Also you probably need to set that panel focusable. I tested it by this code and it seems to work as it should

class HelloWorld extends JPanel implements KeyListener{
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped: "+e);
}
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed: "+e);
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased: "+e);
}
}

class MyFrame extends JFrame {
public MyFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200,200);

HelloWorld helloWorld=new HelloWorld();

helloWorld.addKeyListener(helloWorld);
helloWorld.setFocusable(true);

add(helloWorld);
setVisible(true);
}
public static void main(String[] args) {
new MyFrame();
}
}

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 applying to JPanel (yes, it is focused)

The short answer is, don't use KeyListener, use the Key Bindings API which will allow you to overcome these shortcomings and configure the level of focus required in order for them to be triggered.

See How to Use Key Bindings for more details

Updated

First, you need to stop think in such absolute terms and start thinking in more abstract concepts. Your game shouldn't care HOW something is done, only when something IS down.

The problem is not with the key bindings API but how you see the problem.

For example, you shouldn't care HOW an "up" event is triggered, only that it was. This means that trigger could have come from a joystick, game controller, network server, mind control through the force and even the keyboard. The game would then react to this change in state accordingly.

Key bindings

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class KeyBindingsTest {

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

public KeyBindingsTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public interface InputManager {

public void upWasPerformed(boolean active);
public void downWasPerformed(boolean active);
public void leftWasPerformed(boolean active);
public void rightWasPerformed(boolean active);

}

public static class TestPane extends JPanel implements InputManager {

public static final LineBorder LINE_BORDER = new LineBorder(Color.RED);
public static final EmptyBorder EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);

private JLabel up;
private JLabel down;
private JLabel left;
private JLabel right;

public TestPane() {
setLayout(new GridBagLayout());
up = new JLabel("UP");
up.setBorder(EMPTY_BORDER);

down = new JLabel("DOWN");
down.setBorder(EMPTY_BORDER);

left = new JLabel("LEFT");
left.setBorder(EMPTY_BORDER);

right = new JLabel("RIGHT");
right.setBorder(EMPTY_BORDER);

setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
add(left, gbc);
gbc.gridx++;
gbc.gridy = 0;
add(up, gbc);
gbc.gridy = 2;
add(down, gbc);
gbc.gridx++;
gbc.gridy = 1;
add(right, gbc);

InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right.released");

ActionMap am = getActionMap();
am.put("up.pressed", new UpAction(this, true));
am.put("up.released", new UpAction(this, false));
am.put("down.pressed", new DownAction(this, true));
am.put("down.released", new DownAction(this, false));
am.put("left.pressed", new LeftAction(this, true));
am.put("left.released", new LeftAction(this, false));
am.put("right.pressed", new RightAction(this, true));
am.put("right.released", new RightAction(this, false));
}

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

@Override
public void upWasPerformed(boolean active) {
up.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
}

@Override
public void downWasPerformed(boolean active) {
down.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
}

@Override
public void leftWasPerformed(boolean active) {
left.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
}

@Override
public void rightWasPerformed(boolean active) {
right.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
}

}

public static abstract class InputManagerAction extends AbstractAction {

private InputManager manager;
private boolean activate;

public InputManagerAction(InputManager manager, boolean activate) {
this.manager = manager;
this.activate = activate;
}

public InputManager getManager() {
return manager;
}

public boolean shouldActivate() {
return activate;
}

}

public static class UpAction extends InputManagerAction {

public UpAction(InputManager manager, boolean activate) {
super(manager, activate);
}

@Override
public void actionPerformed(ActionEvent e) {
getManager().upWasPerformed(shouldActivate());
}

}

public static class DownAction extends InputManagerAction {

public DownAction(InputManager manager, boolean activate) {
super(manager, activate);
}

@Override
public void actionPerformed(ActionEvent e) {
getManager().downWasPerformed(shouldActivate());
}

}

public static class LeftAction extends InputManagerAction {

public LeftAction(InputManager manager, boolean activate) {
super(manager, activate);
}

@Override
public void actionPerformed(ActionEvent e) {
getManager().leftWasPerformed(shouldActivate());
}

}

public static class RightAction extends InputManagerAction {

public RightAction(InputManager manager, boolean activate) {
super(manager, activate);
}

@Override
public void actionPerformed(ActionEvent e) {
getManager().rightWasPerformed(shouldActivate());
}

}
}

Now, you have two choices to make, you can change the way you are thinking and take advantage of an API which will solve your problem and make your program more flexible and configurable (as the user might like to change the keys that trigger the events) or your can continue trying to use to an API which is failing to meet your needs and which the community at large will encourage you not to continue to use...

addKeyListener() doesn't work for JPanel

Simply, your panel needs to be focusable. Add in wherever you create the panel:

panel.setFocusable(true);
panel.requestFocusInWindow();

Here's a SSCCE (I suggest asking questions with one of these in the future):

import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleKeyTest {

public static void main(String[] args) {

Runnable r = new Runnable() {

@Override
public void run() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();

frame.getContentPane().add(panel);

panel.addKeyListener(new KeyListener() {

@Override
public void keyTyped(KeyEvent e) {}

@Override
public void keyReleased(KeyEvent e) {}

@Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed " + e.getKeyChar());
}
});

panel.setFocusable(true);
panel.requestFocusInWindow();

frame.setSize(new Dimension(300, 300));
frame.setVisible(true);
}

};

SwingUtilities.invokeLater(r);

}
}

Also, https://www.google.com/search?q=jpanel+keylistener



Related Topics



Leave a reply



Submit