I have created a simple demo. The message "a is typed" will be shown if you trigger the specific key Stroke event on the mainPanel. However, it doesn't work after I press the button below the mainPanel. Here is the KeybindingTest class and its inner classes:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class KeybindingTest {
private JFrame frame;
private MainPanel mainPanel;
private ButtonPanel buttonPanel;
public static void main(String[] args) {
KeybindingTest test = new KeybindingTest();
test.createUI();
}
public void createUI(){
frame = new JFrame("Keybing Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new MainPanel();
buttonPanel = new ButtonPanel();
frame.add(mainPanel,BorderLayout.CENTER);
frame.add(buttonPanel,BorderLayout.SOUTH);
KeybindingListener.getInstance().keybinding(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
@SuppressWarnings("serial")
class MainPanel extends JPanel{
@Override
public Dimension getPreferredSize() {
// TODO Auto-generated method stub
return new Dimension(400, 300);
}
}
@SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
setBackground(Color.green);
JButton enableButton = new JButton("enable");
enableButton.addActionListener(new EnableButtonListener());
JButton disableButton = new JButton("disable");
disableButton.addActionListener(new DisableButtonListener());
add(enableButton);
add(disableButton);
}
}
class EnableButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("enabled");
}
}
class DisableButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("disabled");
}
}
}
Here is the KeybindingListener class and its inner class:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class KeybindingListener {
private static KeybindingListener keybindingListener;
private final String mapKey = "a";
private KeybindingListener(){
//singleton
}
public static KeybindingListener getInstance(){
if (keybindingListener == null) {
keybindingListener = new KeybindingListener();
return keybindingListener;
}else {
return keybindingListener;
}
}
public void keybinding(JPanel mainPanel){
mainPanel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A , 0),mapKey);
mainPanel.getActionMap().put(mapKey, new keyAction());
}
@SuppressWarnings("serial")
class keyAction extends AbstractAction{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("a is typed");
}
}
}
Thank you for your help in advance.
As stated in this answer, JComponent#getInputMap()
is a convenience method for JComponent#getInputMap(WHEN_FOCUSED)
. Since you are adding your key binding to a JPanel
this implies that your panel must have focus to properly work, which is not possible.
You can either add the key binding as is to all the components in your panel or add the key binding to the panel like this:
public void keybinding(JPanel mainPanel){
mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A , 0),mapKey);
mainPanel.getActionMap().put(mapKey, new keyAction());
}
See How Key Bindings Work for a better explanation on this matter.