Jfx Key binding question

OK, I am looking for ideas. I have gone down a couple rabbit holes and made some overly complicated solutions that don’t work.

I am looking for a way to handle keyboard input jme regardless to if jfx is focused or not. But when jfx consumes an event (like typing in a text field, hitting tab to change focus, pressing enter to activate a button) I want that event to not hit jme. Everything else I would like to be forwarded to jme.

An example of a UI where this behavior is desired. When I have my world editor open, I am in third person view. I would like to still be able to use the AWSD keys to walk around, but also want to be able to interact with my jfx menu. Basically, regardless of if jfx has focus I want all game key events to still be forwarded to jme, but if I go to type in a text field in that UI, I do not want those key events to hit jme.

Another example is I have a character creator, and use AWSD to move the character around. I still want those to work after I have moved a slider without having to click off of the jfx ui.

Thoughts?

If an input event occurs in JME - say the keydown event, JME will also receive the key up event even if jfx is focused, so you can continue to move forward after clicking a button or stop when JME is no longer focused.

For buttons and stuff there is a method called loseFocus that you can call after pressing a jfx button or whatever the action is to push the focus straight back to JME.

And those features for fine, but my dilemma is trying to get input to jme regardless of focus.

Like if a user is editing their character, it is confusing to click away from the UI after changing a slider to use the zoom hot keys.

But if you use that method to give JME focus after the slider event they won’t have to…

I went down a similar route to this and I did use the loseFocus approach jayfella suggested in some cases but I didn’t want to do that everywhere so I also used a capture and republish approach. Because the key events bubble up you can do this just at the highest level (obviously keys into text boxes won’t bubble but you probably don’t want that anyway). I used this method to capture and republish:

/**
 * Captures JavaFx key events and republishes them to the main game
 *
 * @param node A node, high in the JavaFX node graph. It will be watched for key events and republish
 * @param keyToBindingRepublishes The codes that JavaFx receives and the main game keybindings they relate to
 */
static void withCaptureAndRepublishKeys(Node node, Map<String, BaseKeyBinding> keyToBindingRepublishes){
    node.setFocusTraversable(true);
    node.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
        if (event.getCode() != null) {
            Optional.ofNullable(keyToBindingRepublishes.get(event.getCode().getName().toLowerCase())).ifPresent(binding -> {
                event.consume();
                binding.setValue(true);
            });
        }
    });
}

You pass it a Node high in the JavaFx node graph and it will capture everything. BaseKeyBinding is part of how I handle key events so you’ll have to substitute with however you handle key events

2 Likes