I have a Swing app that needs to display different sets of controls based on whether the control or alt keys are pressed. I added a KeyListener to the main component, but i
You may consider using the InputMap and ActionMap of some swing components. You can specify with JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
to indicate you want to respond to the given keystroke when either the component or its subcomponents are in focus.
If you don't want to use the InputMap or ActionMap, you could just add the KeyListener to all the child components:
for (Component child : parent.getComponents())
{
child.addKeyListener(keyListener);
}
Just change your getKeyStroke(...)
invocation like so:
InputMap inputMap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK, false), "test1");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, 0, true), "test2");
ActionMap actionMap = panel.getActionMap();
actionMap.put("test1", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("pressed");
}
});
actionMap.put("test2", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("released");
}
});
I took me a lot of trial and error to come up with the correct incantation.
It is important to use getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT), to be able to listen to child and deeper widgets.
It is especially important to specify KeyEvent.CTRL_DOWN_MASK
, in addition to KeyEvent.VK_CONTROL
when looking for control key PRESS events. This particular detail was missing from your modified code example.
You may want to try to use key binding rather than KeyListeners. Key binding is a higher level construct and can listen for key presses even if the component that "listens" doesn't have the focus -- as opposed to KeyListeners. You can find more on these at the Swing tutorials: How to use key bindings
You might be able to use a Global Event Listener.