Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Swing: Key pressed key stroke on an `InputMap` triggers its action several times while holding down the key

I register

getInputMap().put(KeyStroke.getKeyStroke("pressed RIGHT"), "go right");

When testing the code I get: While I hold the right arrow key down, the action is triggered repeatedly and not only once as I would have expected this.

Interestingly

getInputMap().put(KeyStroke.getKeyStroke("released RIGHT"), "stop");

triggers stop only when the key is finally released.

Is there a way to register a key stroke on an input map, so that the associated action is only triggered once at the moment when the key is pressed?

like image 893
ThomasR Avatar asked Nov 01 '13 08:11

ThomasR


People also ask

What is keystroke inputmap and keymap?

KeyStroke: InputMap and Keymap maps one KeyStroke object to a action name or action. KeyStroke class is a member of javax.swing package and any object of this class represents a key or a combination of keys in the keyboard. 2.

What is a keystroke?

A KeyStroke represents a key action on the keyboard, or equivalent input device. KeyStrokes can correspond to only a press or release of a particular key, just as KEY_PRESSED and KEY_RELEASED KeyEvents do; alternately, they can correspond to typing a specific Java character, just as KEY_TYPED KeyEvents do.

What is keystroke class in Java?

KeyStroke class is a member of javax.swing package and any object of this class represents a key or a combination of keys in the keyboard. 2. Technologies Used

Can keystrokes specify modifiers for action events?

In all cases, KeyStrokes can specify modifiers (alt, shift, control, meta, altGraph, or a combination thereof) which must be present during the action for an exact match. KeyStrokes are used to define high-level (semantic) action events.


2 Answers

Documentation of KeyStroke:

A KeyStroke represents a key action on the keyboard, or equivalent input device. KeyStrokes can correspond to only a press or release of a particular key, just as KEY_PRESSED and KEY_RELEASED KeyEvents do; alternately, they can correspond to typing a specific Java character, just as KEY_TYPED KeyEvents do. In all cases, KeyStrokes can specify modifiers (alt, shift, control, meta, altGraph, or a combination thereof) which must be present during the action for an exact match.

To trigger the event only once, at release time, I suggest to register

getInputMap().put(KeyStroke.getKeyStroke("typed RIGHT"), "go right");

The documentation of KeyStroke.getKeyStroke(String) is:

Parses a string and returns a KeyStroke. The string must have the following syntax:

  • modifiers* (typedID | pressedReleasedID)

  • modifiers := shift | control | ctrl | meta | alt | altGraph
  • typedID := typed <typedKey>
  • typedKey := string of length 1 giving Unicode character.
  • pressedReleasedID := (pressed | released) key
  • key := KeyEvent key code name, i.e. the name following "VK_".
  • To trigger the event only once, at press time, I suggest to register the press and release events to manage yourself a latch with a boolean.

    like image 51
    Aubin Avatar answered Sep 27 '22 20:09

    Aubin


    Is there a way to register a key stroke on an input map, so that the associated action is only triggered once at the moment when the key is pressed?

    Remove the keyPressed binding from the InputMap. Then for the keyReleased Action you add the keyPressed binding back to the InputMap.

    However, even this can cause problems because on a Windows OS the sequence of KeyEvents is:

    pressed, pressed, pressed.... released.
    

    This makes sense to me as generally when you hold the key down you want the character to repeat. However, on a Mac I believe the sequence is:

    pressed, released, pressed, released, pressed, released
    

    which doesn't make sense to me and makes it difficult to determine when a key has truly been released.

    like image 28
    camickr Avatar answered Sep 27 '22 20:09

    camickr