如何阻止控件使用KeyEvent?

时间:2013-11-01 21:13:51

标签: javafx-2 javafx-8

我们的应用程序使用带有单个舞台的JavaFX用户界面,该舞台顶部包含一个MenuBar,下面包含许多其他控件。

我们希望使用KeyCode.SPACE(即空格键)作为MenuBar中某个MenuItem的加速器。是的,我知道这不是用于菜单加速器的理想键。这不是我的决定。 :)

无论如何,起初SPACE加速器工作正常:

menuItem.setAccelerator( KeyCombination.valueOf( "SPACE" ) );

但是当我们开始向舞台添加其他控件如TableView时,该加速器停止工作。事实证明,其他控件使用SPACE用于它们自己的目的,并在它回到MenuBar之前使用KeyEvent。

然后我们决定我们不需要SPACE来处理其他控件,因此我通过使用事件过滤器“解决”了问题。在它进入其他控件之前,它会窃取我的MenuItem的SPACE KeyEvent:

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();
     }
  }
});

这似乎有效,但我希望可能会有一个更清洁,不那么脆弱的解决方案。特别是,我真的想找到一种方法告诉其他控件(比如TableView)停止使用SPACE KeyEvent。

这可能吗?

1 个答案:

答案 0 :(得分:1)

我遇到类似的问题,一些控件,特别是文本输入控件,使用定义为菜单加速器的功能键。为了解决这个问题,我找到了一种更通用的方法,使菜单加速器优先于控件的主要消耗:

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;
            }
        }
    }
});

这比问题中提供的解决方案稍微不那么脆弱,因为它不会将密钥硬编码到事件过滤器中,并且它允许所有菜单项处理由来自Scene.getAccelerators()的Runnables完成。这些Runnables在方法com.sun.javafx.scene.control.ControlAcceleratorSupport中的实现类doAcceleratorInstall中定义。

我更喜欢将此过滤器添加到每个违规控件中,但它当然也可以安装在舞台上。