0

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

这是步骤(窗口平台)

  1. 按键Alt_
  2. 可以看到助记符
  3. 按键F_
  4. 下拉菜单并获得焦点
  5. 按箭头 ( ->) 键
  6. 如下错误

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 )

但是当我用鼠标单击菜单栏时,它不会发生。

任何解决方案?

4

3 回答 3

1

必须同意 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 程序在其他方面功能完美,可以动态地更改其菜单(并且一举两得),它可能会很有用。

于 2014-01-24T18:51:14.700 回答
0

下面的自我解决方法。

我发现这是 Windows 7 上的 Java FX 2.2 错误。

脚步::

  1. 将 keyevent 添加到舞台
  2. consume()获得时的事件RIGHTLEFT以菜单为重点的事件。
  3. 自己实施

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();
                }
            }
        }
    }
});
于 2013-10-29T04:54:01.567 回答
0

我发现显示菜单和支持导航而不在其他地方获得一堆空指针异常和样式更改的唯一可靠方法是模拟实际的用户事件流:

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();
}
于 2014-07-08T22:53:01.053 回答