JavaFX:禁用使用键盘控制单选按钮

Dan*_*lBK 3 java javafx focus radio-button

我正在开始使用 JavaFX,并且已经构建了一个小俄罗斯方块游戏。现在一切正常,但最后我决定添加一组单选按钮来选择难度 - 在这里我遇到了一个问题:突然LEFT/ RIGHT/ UP/DOWN键只切换单选按钮,不再控制游戏玩法。

为了处理游戏玩法,我在场景中添加了一个按键事件侦听器:

public void setKeyEventHandler() {
    game.getScene().setOnKeyPressed(Field::handleKeyEvent);
}

private static void handleKeyEvent(KeyEvent event) {
    // ... handle the event to move the figure
}
Run Code Online (Sandbox Code Playgroud)

但正如我所说,自从我添加了单选按钮后,这不再执行。有没有办法禁用使用键盘键更改单选按钮并使它们只能通过鼠标点击更改?我需要以某种方式从他们身上移开焦点吗?但是如何?

编辑:也许我应该补充一点,我只是使用该setOnAction()函数来处理单选按钮的事件,例如:

classicModeButton.setOnAction((e) -> interestingMode = false); 
interestingModeButton.setOnAction((e) -> interestingMode = true);
Run Code Online (Sandbox Code Playgroud)

DVa*_*rga 6

第一种方法:

你可以让你的RadioButtons不可聚焦

通过此更改,箭头键的默认键侦听器将不再更改收音机的状态,因为它们不会聚焦(即使被鼠标选中):

classicModeButton.setFocusTraversable(false);
interestingModeButton.setFocusTraversable(false);
Run Code Online (Sandbox Code Playgroud)

这只会工作,如果你没有其他可聚焦Node小号上的Scene,否则他们将处理关键事件之前,它可以通过屏幕上的事件处理程序进行处理。如果您有其他节点,请检查第二种方法。

一个示例片段:

// Init the variables
BooleanProperty interestingMode = new SimpleBooleanProperty(false);
RadioButton classicModeButton = new RadioButton("Classic");
RadioButton interestingModeButton = new RadioButton("Interesting");
ToggleGroup tg = new ToggleGroup();

classicModeButton.setToggleGroup(tg);
interestingModeButton.setToggleGroup(tg);
tg.selectToggle(classicModeButton);

// The radios should be not focusable
classicModeButton.setFocusTraversable(false);
interestingModeButton.setFocusTraversable(false);

// On toggle-change, the mode will be changed
interestingMode.bind(tg.selectedToggleProperty().isEqualTo(interestingModeButton));

// Just print the changes
tg.selectedToggleProperty().addListener((observable, oldValue, newValue) ->
        System.out.println((newValue == interestingModeButton) ? "Hmm, interesting" : "Classic .. boring"));

scene.setOnKeyPressed(e -> 
        System.out.println((e.getCode().isArrowKey()) ? "Arrow pressed!" : "Other pressed, I don't care!"));
Run Code Online (Sandbox Code Playgroud)

第二种方法:

您可以通过向 中添加事件过滤器而不是事件处理程序来处理键事件Scene,并使用该事件。这将捕获已经处于捕获阶段(而不是冒泡阶段)的事件,因此该事件甚至不会到达您的 (focusable) Nodes:

scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
    System.out.println((event.getCode().isArrowKey()) ? "Arrow pressed!" : "Other pressed, I don't care!");
    event.consume();
});
Run Code Online (Sandbox Code Playgroud)

有了这个,所有按键事件都会被捕获,但当然可以“让一些事件”通过。

更多关于如何传递事件的信息可以在这里找到(例如)。