Java Swing: нажатие клавиши на клавише InputMap запускает действие несколько раз, удерживая клавишу нажатой
Я регистрируюсь
getInputMap().put(KeyStroke.getKeyStroke("pressed RIGHT"), "go right");
При тестировании кода, который я получаю: удерживая правую клавишу со стрелкой вниз, действие запускается повторно, а не только один раз, как я и ожидал.
что интересно
getInputMap().put(KeyStroke.getKeyStroke("released RIGHT"), "stop");
триггеры останавливаются только тогда, когда ключ наконец отпущен.
Есть ли способ зарегистрировать нажатие клавиши на карте ввода, чтобы связанное действие запускалось только один раз в момент нажатия клавиши?
3 ответа
Документация KeyStroke:
KeyStroke представляет действие клавиши на клавиатуре или эквивалентном устройстве ввода. KeyStrokes может соответствовать только нажатию или отпусканию определенной клавиши, так же, как KEY_PRESSED и KEY_RELEASED KeyEvents; поочередно, они могут соответствовать вводу конкретного символа Java, как это делают KEY_TYPED KeyEvents. Во всех случаях KeyStrokes может указывать модификаторы (alt, shift, control, meta, altGraph или их комбинации), которые должны присутствовать во время действия для точного соответствия.
Чтобы вызвать событие только один раз, во время выпуска, я предлагаю зарегистрироваться
getInputMap().put(KeyStroke.getKeyStroke("typed RIGHT"), "go right");
Документация KeyStroke.getKeyStroke(String):
Разбирает строку и возвращает KeyStroke. Строка должна иметь следующий синтаксис:
модификаторы * (typedID |ressedReleasedID) модификаторы:= сдвиг | контроль | Ctrl | мета | альт | altGraph typedID:= typed typedKey:= строка длиной 1, дающая символ Unicode. нажимаем ReleasedID:= (нажата | отпущена) клавиша key:= имя кода ключа KeyEvent, то есть имя, следующее за "VK_".
Чтобы вызвать событие только один раз, во время печати, я предлагаю зарегистрировать события прессы и выпустить, чтобы управлять защелкой с логическим значением.
Есть ли способ зарегистрировать нажатие клавиши на карте ввода, чтобы связанное действие запускалось только один раз в момент нажатия клавиши?
Удалите связывание keyPressed из InputMap. Затем для действия KeyReleased вы добавляете привязку keyPressed обратно в InputMap.
Однако даже это может вызвать проблемы, потому что в ОС Windows последовательность KeyEvents:
pressed, pressed, pressed.... released.
Это имеет смысл для меня, так как обычно, когда вы держите клавишу нажатой, вы хотите, чтобы персонаж повторился. Тем не менее, на Mac я считаю, что последовательность:
pressed, released, pressed, released, pressed, released
что не имеет смысла для меня и затрудняет определение, когда ключ действительно был выпущен.
Событие "типизированный ключ" действует в зависимости от поведения платформы, которое, как стандарт до 1980-х годов, всегда включало автоповтор. Это будет обусловлено низкоуровневыми событиями из ОС.
Вы могли бы попытаться не удерживать клавиши? Вы не должны нажимать на клавиатуру, это точный инструмент.
Вы можете изменить привязку нажатия клавиш (чтобы избежать автоматического повторения) или иным образом использовать пользовательский прослушиватель событий и обрабатывать только низкоуровневое событие keydown/ keyup один раз. События низкого уровня могут, однако, выставлять коды клавиш (так как они ниже уровня фактического набора какого-либо одного символа), а не символы.