【问题标题】:JavaFX Detect mutliple keyboard keys pressed simultaneouslyJavaFX检测同时按下的多个键盘键
【发布时间】:2017-02-16 19:57:44
【问题描述】:

正如标题所说,我想检测多个键盘键同时按下(同时)并在一段时间内被按下(同时)。我正在尝试在 Scene 上添加多个事件处理程序,但它不起作用:

EventHandler<KeyEvent> handler1 = key -> {
     //logic1 here
}

EventHandler<KeyEvent> handler2 = key -> {
     //logic1 here
}

getScene().addEventHandler(KeyEvent.KEY_PRESSED, handler1);
getScene().addEventHandler(KeyEvent.KEY_PRESSED, handler2);

我为什么要这样做:

我有一些代码,我想根据用户按下的keyboard keys 调整矩形的大小。例如,如果用户按下RIGHT ARROW,矩形将从右侧增加,如果用户按下@ 987654326@矩形从上往下递增。

问题:

但是当用户同时按下 [RIGHT ARROW] 和 [UP ARROW] 并保持按下状态时,上述两个动作必须同时发生,而不仅仅是其中一个。

【问题讨论】:

  • 该问题带有 [javafx] 标记,因此不需要在标题中说明。
  • 虽然在标题中包含 JavaFX 时它也在标签中有点多余,但考虑到 JavaFX 问题也被标记为 Java 标记时出现的不适当答案的数量,这可能有助于有它。 (显然人们通常不阅读标签......)。
  • @James_D 说得有道理,我只是按照Should questions include “tags” in their titles? 所说的话。
  • @JonnyHenly 也许更好的选择是省略 [java] 标签而只使用 [javafx] 标签....

标签: java javafx


【解决方案1】:

只需操作一些布尔属性:

private BooleanProperty upPressed = new SimpleBooleanProperty();
private BooleanProperty rightPressed = new SimpleBooleanProperty();

private BooleanBinding anyPressed = upPressed.or(rightPressed);

// ...

getScene().setOnKeyPressed(e -> {
    if (e.getCode() == KeyCode.UP) {
        upPressed.set(true);
    }
    if (e.getCode() == KeyCode.RIGHT) {
        rightPressed.set(true);
    }
});

getScene().setOnKeyReleased(e -> {
    if (e.getCode() == KeyCode.UP) {
        upPressed.set(false);
    }
    if (e.getCode() == KeyCode.RIGHT) {
        rightPressed.set(false);
    }
});

如果同时按下两个键,则两个属性都将为真,因此您可以使用布尔属性注册侦听器,或根据需要在AnimationTimer 中检查它们,例如:

double delta = .. ;

AnimationTimer timer = new AnimationTimer() {
    @Override
    public void handle(long timestamp) {
        if (upPressed.get()) {
            rect.setY(rect.getY()-delta);
            rect.setHeight(rect.getHeight() + delta);
        }
        if (rightPressed.get()) {
            rect.setWidth(rect.getWidth() + delta);
        }
    }
};

anyPressed.addListener((obs, wasPressed, isNowPressed) -> {
    if (isNowPressed) {
        timer.start();
    } else {
        timer.stop();
    }
});

【讨论】:

  • 由于某种原因,AnimationTimer 永远不会启动...即使我按住向上箭头键(例如,我有一个println()inside handle(long timestamp),但没有打印任何内容)。也许BooleanBinding 不起作用...
  • @GoXR3Plus 尝试将anyPressed 设为实例变量,而不是本地变量(显然您必须对属性执行相同操作)。当它超出范围时可能会被垃圾收集。
  • 完美,现在它可以工作了,但我需要再想一想,我怎么能延迟到AnimationTimer,因为我不需要这么快调整矩形的大小......
  • 只是减少delta的值? timestamp 参数是以纳秒为单位的时间戳,因此您基本上可以设置像素/秒的速度,如果您想要非常精确,则可以根据该速度计算改变多少。但假设它每秒被调用大约 60 次也是相当安全的。
  • 如果用户在窗口聚焦时按下键并在没有聚焦时释放它,这似乎会失败 - 应用程序永远不会获得释放事件。
猜你喜欢
  • 2019-05-21
  • 2018-10-24
  • 2017-07-31
  • 1970-01-01
  • 2016-09-25
  • 2014-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多