【问题标题】:JavaFX: Disable controlling RadioButtons with keyboardJavaFX:禁用使用键盘控制 RadioButtons
【发布时间】:2018-05-30 03:11:06
【问题描述】:

我正在开始使用 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
}

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

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

classicModeButton.setOnAction((e) -> interestingMode = false); 
interestingModeButton.setOnAction((e) -> interestingMode = true);

【问题讨论】:

    标签: java javafx radio-button focus


    【解决方案1】:

    我以前从未处理过这种情况,所以我只是在这里吐槽一个想法,但也许你可以为javafx.scene.input.KeyEvent 实现一个处理程序。

    在您的处理程序中,您可能会说:

    if(event.getCode().isNavigationKey()){
        // Some navigation key was pressed
        event.consume(); // prevent further propagation 
        yourGamesControlElement.requestFocus(); // transfer focus
        handleKeyMovementInGame(event.getCode()); // handle the action
    }
    

    这种检测方法的一个好处是isNavigationKey() 将为您处理所有键码检查,包括检查常规箭头键和数字键盘箭头键。

    我还建议查看 this GitHub Gist,其中讨论了使用 KeyEvents 来防止 JavaFX 在按下 Tab 键时转移焦点,以及 JavaFX KeyCode documentation 以了解更多想法和实现细节。

    【讨论】:

    • 对我来说,当 Spinner 捕获我不希望它捕获的箭头键按下时,除了错误的 Spinner 之外,为场景中的其他组件执行 xxxx.requestFocus() 帮助了我。它可能也适用于 RadioButtons。
    【解决方案2】:

    第一种方法:

    你可以让你的RadioButtons not focusable

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

    classicModeButton.setFocusTraversable(false);
    interestingModeButton.setFocusTraversable(false);
    

    这只有在您的Scene 上没有其他可聚焦的Nodes 时才有效,否则他们将在事件处理程序处理关键事件之前处理它屏幕。如果您有其他节点,请检查第二种方法。

    sn-p 示例:

    // 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!"));
    

    第二种方法:

    您可以通过向Sceneconsume the event 添加event filter 而不是事件处理程序来处理键事件。这将捕获已经处于捕获阶段(而不是冒泡阶段)的事件,因此该事件甚至不会到达您的(可聚焦的)Nodes:

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

    这样,所有按键事件都会被捕获,当然也可以“让某些事件”通过。

    有关事件如何传递的更多信息,请参见(例如)here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 2017-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多