JavaFX 如何区分 keyPressed X 和 Keys X + Y 的组合
JavaFX How can I distinguish between a keyPressed X and a combination of Keys X + Y
我希望我的应用程序 (JavaFx 14) 在按下键 "a" 时执行某些操作,并且我还希望应用程序在具有相同键 "a" 和 "b" 被按下。目标是只调用一种方法。按 a 的方法或按 a + b 的方法。我试着用一个带有键码的可观察列表来做,但是所有的方法都被调用了。
private ObservableList<KeyCode> keys = FXCollections.observableArrayList();
private void keyboardShortcuts(Button[] buttons){
// collect pressed key
scene.addEventFilter(KeyEvent.KEY_PRESSED, (e) -> {
if (!keys.contains(e.getCode())) {
keys.add(e.getCode());
}
e.consume();
});
// remove pressed key when it is released
scene.setOnKeyReleased((e) -> {
keys.remove(e.getCode());
e.consume();
});
keys.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
if(keys.size() == 1) {
if(keys.contains(KeyCode.A)) {
foo();
}
if(keys.contains(KeyCode.B)) {
foo2();
}
}
if(keys.size() == 2) {
if(keys.contains(KeyCode.A) && keys.contains(KeyCode.B)) {
foo3();
}
}
}
});
}
当用户"presses two keys"时,两个按键不可能同时发生,因此其中一个按键必然会先于另一个被检测到。可能这里最好的方法是确保其中一个键(比如 B)没有它自己的功能。这样用户将学会始终先按下 B,然后按下 A,同时按住 B(这是我们键入的方式,使用修饰键,例如 SHIFT 和 CTRL).
如果您确实希望两个键都有自己的功能,但同时按下两个键时功能不同"at the same time",那么您唯一的选择是实现延迟处理单个键的按下,等待查看在延迟到期之前是否按下了另一个键。当然,这是以响应速度为代价的。
这是一个实现,使用短(25 毫秒)PauseTransition
作为延迟。 (我也改为使用 ObservableSet
,它清理了一些逻辑。)
private ObservableSet<KeyCode> keys = FXCollections.observableSet();
private PauseTransition keyDelay = new PauseTransition(Duration.millis(25));
private void keyboardShortcuts(Scene scene){
// collect pressed key
scene.addEventFilter(KeyEvent.KEY_PRESSED, (e) -> {
keys.add(e.getCode());
e.consume();
});
// remove pressed key when it is released
scene.setOnKeyReleased((e) -> {
keys.remove(e.getCode());
e.consume();
});
keys.addListener((Change<? extends KeyCode> c) -> {
if (keys.size() <= 1) {
keyDelay.playFromStart();
} else {
keyDelay.stop();
checkKeys();
}
});
keyDelay.setOnFinished(e -> checkKeys());
}
private void checkKeys() {
if(keys.contains(KeyCode.A) && keys.contains(KeyCode.B)) {
System.out.println("A and B");
} else if(keys.contains(KeyCode.A)) {
System.out.println("A only");
} else if(keys.contains(KeyCode.B)) {
System.out.println("B only");
}
}
我希望我的应用程序 (JavaFx 14) 在按下键 "a" 时执行某些操作,并且我还希望应用程序在具有相同键 "a" 和 "b" 被按下。目标是只调用一种方法。按 a 的方法或按 a + b 的方法。我试着用一个带有键码的可观察列表来做,但是所有的方法都被调用了。
private ObservableList<KeyCode> keys = FXCollections.observableArrayList();
private void keyboardShortcuts(Button[] buttons){
// collect pressed key
scene.addEventFilter(KeyEvent.KEY_PRESSED, (e) -> {
if (!keys.contains(e.getCode())) {
keys.add(e.getCode());
}
e.consume();
});
// remove pressed key when it is released
scene.setOnKeyReleased((e) -> {
keys.remove(e.getCode());
e.consume();
});
keys.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
if(keys.size() == 1) {
if(keys.contains(KeyCode.A)) {
foo();
}
if(keys.contains(KeyCode.B)) {
foo2();
}
}
if(keys.size() == 2) {
if(keys.contains(KeyCode.A) && keys.contains(KeyCode.B)) {
foo3();
}
}
}
});
}
当用户"presses two keys"时,两个按键不可能同时发生,因此其中一个按键必然会先于另一个被检测到。可能这里最好的方法是确保其中一个键(比如 B)没有它自己的功能。这样用户将学会始终先按下 B,然后按下 A,同时按住 B(这是我们键入的方式,使用修饰键,例如 SHIFT 和 CTRL).
如果您确实希望两个键都有自己的功能,但同时按下两个键时功能不同"at the same time",那么您唯一的选择是实现延迟处理单个键的按下,等待查看在延迟到期之前是否按下了另一个键。当然,这是以响应速度为代价的。
这是一个实现,使用短(25 毫秒)PauseTransition
作为延迟。 (我也改为使用 ObservableSet
,它清理了一些逻辑。)
private ObservableSet<KeyCode> keys = FXCollections.observableSet();
private PauseTransition keyDelay = new PauseTransition(Duration.millis(25));
private void keyboardShortcuts(Scene scene){
// collect pressed key
scene.addEventFilter(KeyEvent.KEY_PRESSED, (e) -> {
keys.add(e.getCode());
e.consume();
});
// remove pressed key when it is released
scene.setOnKeyReleased((e) -> {
keys.remove(e.getCode());
e.consume();
});
keys.addListener((Change<? extends KeyCode> c) -> {
if (keys.size() <= 1) {
keyDelay.playFromStart();
} else {
keyDelay.stop();
checkKeys();
}
});
keyDelay.setOnFinished(e -> checkKeys());
}
private void checkKeys() {
if(keys.contains(KeyCode.A) && keys.contains(KeyCode.B)) {
System.out.println("A and B");
} else if(keys.contains(KeyCode.A)) {
System.out.println("A only");
} else if(keys.contains(KeyCode.B)) {
System.out.println("B only");
}
}