我们的应用程序使用带有单个舞台的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。
这可能吗?
答案 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
中定义。
我更喜欢将此过滤器添加到每个违规控件中,但它当然也可以安装在舞台上。