From a java textbook, I copied a program that lets users move a body of text around their screens, using their arrow keys. The program will only work on non-OSX operating systems (I confirmed this with my mac and, presumably, it ran on the computer of the java textbook writer). I found a resolution to this discrepancy (Java KeyEvents on Mac), which recommended that I use KeyBindings instead of ActionListeners to process the firing and listening of events, with the vague rationale that
Note: To define special reactions to particular keys, use key bindings instead of a key listener.
While my code now runs, I still don't understand the resolution's rationale. Why is it that KeyBindings, but not KeyListeners, detect Mac arrowkey commands? The arrowkey commands are not "special reactions" that involve multiple keys (like Shift + a + b).
This is a segment of what I copied, the code that used a KeyListener
addKeyListener(new KeyListener()
{
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode())
{
case KeyEvent.VK_DOWN:
y -= 10;
break;
case KeyEvent.VK_UP:
y += 10;
break;
//.... more code
And a segment with KeyBindings
class DownAction extends AbstractAction
{
@Override
public void actionPerformed(ActionEvent e) {
y += 10;
repaint();
}
}
class UpAction extends AbstractAction
{
@Override
public void actionPerformed(ActionEvent e) {
y -= 10;
repaint();
}
}
this.getInputMap().put(KeyStroke.getKeyStroke("DOWN"),"down");
this.getActionMap().put("down", new DownAction ());
this.getInputMap().put(KeyStroke.getKeyStroke("UP"),"up");
this.getActionMap().put("up", new UpAction ());
// this segment is within a class that extends JPane
With a key listener, "a component must have the keyboard focus." In contrast, key bindings "take the containment hierarchy into account." You may have encountered a platform-specific vagary in how the containment hierarchy is searched or how the focus subsystem works.
As a concrete example,
LinePanel
contains aControlPanel
containing a number ofMoveButton
instances. EachMoveButton
has anAction
that moves the line. The enclosingControlPanel
also gets aWHEN_IN_FOCUSED_WINDOW
map entry that binds the matching arrow key to anAction
that clicks the corresponding button. In this way, a particular arrow buttons displays visual feedback, even if another button has focus.