Q:

How can I stop controls from using a KeyEvent?

Our application uses a JavaFX user interface with a single Stage that contains a MenuBar along the top, and a number of other Controls below that.
We want to use KeyCode.SPACE (i.e. the spacebar) as the accelerator for one of the MenuItems in our MenuBar.  Yes, I'm aware that this is not an ideal key to use for a menu accelerator.  It's not my decision.  :)
Anyhow, at first the SPACE accelerator worked fine:
menuItem.setAccelerator( KeyCombination.valueOf( "SPACE" ) );

But as we started adding other Controls like TableView to our Stage, that accelerator stopped working.  It turns out those other Controls use SPACE for their own purposes, and consume the KeyEvent before it ever gets back to the MenuBar.
So then we decided we don't need SPACE to work on those other Controls and thus I "solved" the problem by using an event filter.  It steals the SPACE KeyEvent for my MenuItem before it ever gets to those other controls:
stage.addEventFilter( KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
  public void handle( KeyEvent e ) {
     if ( e.getCode() == KeyCode.SPACE &&
        !(e.getTarget() instanceof TextInputControl) && 
        !menuItem.isDisable() ) {
           e.consume();
           menuItem.fire();
     }
  }
});

This seems to work, but I'm hoping there might be a cleaner, less fragile solution.  In particular, I'd really like to find a way to tell the other Controls (like the TableView) to just stop consuming the SPACE KeyEvent.
Is this possible?

A:

I had a similar problem that some controls, in particular text input controls, consume function keys that are defined as menu accelerators. To work around this, I found a slightly more generic way to make the menu accelerators take precedence over a control's key consumption:
control.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent event) {
        Scene scene = control.getScene();
        if (scene == null) {
            return;
        }
        Map<KeyCombination,Runnable> accelerators = scene.getAccelerators();
        for (KeyCombination keyCombination : accelerators.keySet()) {
            if (keyCombination.match(event)) {
                accelerators.get(keyCombination).run();
                event.consume();
                return;
            }
        }
    }
});

This is a little less fragile than the solution presented in the question as it does not hard code the keys into the event filter and it lets all the menu item handling be done by the Runnables that comes from Scene.getAccelerators(). These Runnables are defined in the implementation class com.sun.javafx.scene.control.ControlAcceleratorSupport in method doAcceleratorInstall.
I prefer to add this filter to each offending control, but it could of course also be installed on the stage. 

