在JAVAFX中,我正在使用快捷方式使用setMnemonicParsing(true)
来自谷歌搜索的代码如下
VBox mainLayout = new VBox();
MenuBar menuBar = new MenuBar();
Menu menu1 = new Menu("_File");
menu1.setMnemonicParsing(true);
menu1.getItems().addAll(new MenuItem("Menu 1"), new MenuItem("Menu 2"));
Menu menu2 = new Menu("_Other");
menu2.setMnemonicParsing(true);
menu2.getItems().addAll(new MenuItem("Other 1"), new MenuItem("Other 2"));
menuBar.getMenus().setAll(menu1, menu2);
mainLayout.getChildren().setAll(menuBar);
Scene scene = new Scene(mainLayout, 300, 100);
stage.setTitle("Demo of mnemonic");
stage.setScene(scene);
stage.sizeToScene();
stage.show();
这是步骤(窗口平台)
- 按 Alt 键
- 可以看到助记字母
- 按 F 键
- 下拉菜单并获得焦点
- 按箭头(->)键
- 如下所示的错误
java.lang.NullPointerException at com.sun.javafx.scene.control.skin.MenuBarSkin.isMenuEmpty(MenuBarSkin.java:728) at com.sun.javafx.scene.control.skin.MenuBarSkin.showNextMenu(MenuBarSkin.java:781)
但是当我用鼠标单击菜单栏时,它不会发生。
有什么解决办法吗?
必须同意 Jamal 的观点,重担落在我们这些低级程序员身上,直到 Oracle 修复它。我对他的修复程序进行了扩展,也许只需一两次修改,就可以使用任意菜单。
stage.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
final int size = menuBar.getMenus().size();
boolean showing = false;
int index = 0;
for(index = 0; index < menuBar.getMenus().size(); ++index) {
if(menuBar.getMenus().get(index).isShowing()) {
showing = true;
break;
}
}
index = (index < 0 ? menuBar.getMenus().size() + index : index) % size;
if(showing) {
Menu menu1 = null, menu2 = null;
menu1 = menuBar.getMenus().get(index);
if(event.getCode() == KeyCode.RIGHT) {
event.consume(); // remove event for next step
menu2 = menuBar.getMenus().get((index + 1) % size);
menu1.hide();
menu2.show();
}
else if(event.getCode() == KeyCode.LEFT) {
event.consume(); // remove event for next step
menu1 = menuBar.getMenus().get(index);
menu2 = menuBar.getMenus().get((index - 1) < 0 ? size + (index - 1) : (index - 1));
menu1.hide();
menu2.show();
}
}
}
});
就个人而言,我认为错误修复应该尽可能严格,这需要任意菜单栏大小。因此,如果您像我一样,遇到一个功能完美的JavaFX程序的错误,该程序可以动态更改其菜单(并且只需一把帽子),它可能会很有用。
下面的自我解决方法。
我发现这是Windows 7上的Java FX 2.2错误。
步骤::
- 将密钥事件添加到舞台
- 获得
RIGHT
时consume()
事件;LEFT
以菜单为重点的活动。 - 实现自己
stage.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if(menu1 .isShowing() || menu2 .isShowing() || menu2 .isShowing()) {
if(event.getCode() == KeyCode.RIGHT) {
log.debug("right");
event.consume(); // remove event for next step
if(menu1.isShowing()) {
menu1.hide();
menu2.show();
}
else if(menu2.isShowing()) {
menu2.hide();
menu3.show();
}
else if(menu3.isShowing()) {
menu3.hide();
menu1.show();
}
}
else if(event.getCode() == KeyCode.LEFT) {
log.debug("left");
event.consume();
if(menu1.isShowing()) {
menu1.hide();
menu3.show();
}
else if(menu2.isShowing()) {
menu2.hide();
menu1.show();
}
else if(menu3.isShowing()) {
menu3.hide();
menu2.show();
}
}
}
}
});
我发现显示菜单和支持导航而不会在其他地方获得一堆空指针异常和样式更改的唯一可靠方法是模拟实际的用户事件流:
MenuBar menuBar; // given a menuBar not null and not empty
KeyEvent evt; // and some event hook not currently consumed
boolean handled = true;
HANDLED:
do
{
do
{
// do your handling
Node n = menuBar;
try
{
while (!(n instanceof MenuButton) && (n instanceof Parent))
{
n = ((Parent)n).getChildrenUnmodifiable().get(0);
}
}
catch (IndexOutOfBoundsException e)
{
// This should not be possible if there exists menu items in the menu bar...
break;
}
if (!(n instanceof MenuButton))
{
// This should not be possible if there exists menu items in the menu bar...
break;
}
// avoid null exceptions in glass pane on immediate click up/down
// and PREVENT unwanted style changes in de-selected state display.
EventHandler<? super MouseEvent> mouseHandler = n.getOnMouseEntered();
if (mouseHandler != null)
{
mouseHandler.handle(null);
}
// perform the "focusing and invocation" of the menu button
Event.fireEvent(n, MouseEvent.impl_mouseEvent(0, 0, 0, 0, MouseButton.PRIMARY, 1, false, false, false, false, false, true, false, false, false, MouseEvent.MOUSE_PRESSED));
// null out the state machine where the mouse is concerned
// prevent null exceptions in glasspane handlers in subsequent navigation movements
Event.fireEvent(n, MouseEvent.impl_mouseEvent(0, 0, 0, 0, MouseButton.PRIMARY, 0, false, false, false, false, false, false, false, false, false, MouseEvent.MOUSE_RELEASED));
break HANDLED;
} while (false);
// non-standard termination
handled = false;
} while (false);
if (handled)
{
evt.consume();
}