5

我注册

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

在测试我得到的代码时:当我按住右箭头键时,该动作被重复触发,而不仅仅是我预期的一次。

有趣的是

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

触发器仅在最终释放键时停止。

有没有办法在输入映射上注册击键,以便在按下键时只触发一次相关操作?

4

3 回答 3

6

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 | pressReleasedID)

  • 修饰符 := 移位 | 控制 | 控制 | 元 | 替代 | 替代图
  • typedID := typed <typedKey>
  • typedKey := 长度为 1 的字符串,给出 Unicode 字符。
  • pressReleasedID := (按下 | 释放) 键
  • key := KeyEvent 键码名称,即“VK_”后面的名称。

  • 为了只触发一次事件,在新闻发布时,我建议注册新闻和释放事件来管理自己的布尔值闩锁。

    于 2013-11-01T08:31:50.060 回答
    3

    有没有办法在输入映射上注册击键,以便在按下键时只触发一次相关操作?

    从 InputMap 中移除 keyPressed 绑定。然后对于 keyReleased Action,将 keyPressed 绑定添加回 InputMap。

    但是,即使这样也可能导致问题,因为在 Windows 操作系统上,KeyEvents 的顺序是:

    pressed, pressed, pressed.... released.
    

    这对我来说很有意义,因为通常当您按住键时您希望角色重复。但是,在 Mac 上,我相信顺序是:

    pressed, released, pressed, released, pressed, released
    

    这对我来说没有意义,并且很难确定何时真正释放了密钥。

    于 2013-11-01T14:56:23.943 回答
    1

    “key typed”事件按平台行为运行——自 1980 年代以来,作为标准,它始终包括自动重复。这将由来自操作系统的低级事件驱动。

    你可以试试按住键吗?你不应该捣碎键盘,它是一种精密仪器。

    您可以更改击键绑定(以避免接收自动重复)或以其他方式使用自定义事件侦听器并仅处理低级 keydown/keyup 事件一次。然而,低级事件可能会暴露键码因为它们低于实际键入任何一个字符的级别)而不是characters

    于 2013-11-01T08:33:35.180 回答