问题
I got a problem with the KeyListener not responding(due to not gaining focus) when I switch between JPanels.
I have Google'd this and know that to fix this problem I need to use KeyBindings, but I don't like KeyBindings. So I was wondering, is there any other way?
Here is the init code of the JPanel that has an unresponsive KeyListener:
public void init()
{
setFocusable(true);
requestFocusInWindow();
requestFocus();
addMouseListener(new MouseInput());
addMouseMotionListener(new MouseInput());
addMouseWheelListener(new MouseInput());
addKeyListener(new KeyInput(p));
t = new Timer(10, this);
t.start();
}
Feel free to ask for more code samples if you need to!
回答1:
The hacky solution is to call requestFocusInWindow()
on the JPanel
to make sure it has focus for KeyListener
/KeyAdapter
this should only be called after the Componnet has been added (though to be sure my component has focus I called it after the JFrame
is refreshed via revalidate()
and repaint()
) for example:
public class MyUI {
//will switch to the gamepanel by removing all components from the frame and adding GamePanel
public void switchToGamePanel() {
frame.getContentPane().removeAll();
GamePanel gp = new GamePanel();//keylistener/keyadapter was added to Jpanel here
frame.add(gp);//add component. we could call requestFocusInWindow() after this but to be 98% sure it works lets call after refreshing JFrame
//refresh JFrame
frame.pack();
frame.revalidate();
frame.repaint();
gp.requestFocusInWindow();
}
}
class GamePanel extends JPanel {
public GamePanel() {
//initiate Jpanel and Keylistener/adapter
}
}
However you should use Swing KeyBinding
s (+1 to @Reimeus comment).
Have a read here to get familiar with them:
- How to Use Key Bindings
Now that you have read that lets show another example to help clarify (though Oracle did a good job)
If we wanted to add a KeyBinding
to a certain JComponent
i.e JButton
for Esc you would do:
void addKeyBinding(JComponent jc) {
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "esc pressed");
jc.getActionMap().put("esc pressed", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Esc pressed");
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), "esc released");
jc.getActionMap().put("esc released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Esc released");
}
});
}
the above method would be called like:
JButton b=..;//create an instance of component which is swing
addKeyBinding(b);//add keybinding to the component
Please note:
1) You would not need both KeyBindings
, I just showed how to get different key state and act appropriately using Keybindings
.
2) This method will add a Keybinding
which will be activated as long as Esc is pressed and the component is in the window which has focus, you can change this by specifying another InputMap
i.e:
jc.getInputMap(JComponent.WHEN_FOCUSED).put(..);//will only activated when component has focus
来源:https://stackoverflow.com/questions/14004263/java-keylistener-not-responding-after-switching-jpanels