除非具有菜单项,否则无法单击菜单

问题描述 投票:1回答:1

我正在尝试使用javafx对菜单栏中菜单上的click事件添加操作。事实是,我看到了很多关于它的文章,但没有答案对我有用。我设法使用菜单上的“正在显示”来做到这一点,这很好,but仅当菜单中至少有一个菜单项时才触发此事件(和其他事件一样)。这不是我想要的东西,但我现在别无选择。

这里是fxml:

    <?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.HangmanGameFXViews.view.MenuesActionsControlleur">
   <top>
      <MenuBar fx:id="menusBar" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" onMouseReleased="#switchToAbout" prefWidth="400.0" BorderPane.alignment="CENTER">
         <menus>
            <Menu mnemonicParsing="false" text="Fichiers">
               <items>
                  <MenuItem mnemonicParsing="false" text="Nouveau" />
                  <MenuItem mnemonicParsing="false" onAction="#switchToScore" text="Scores" />
                  <MenuItem mnemonicParsing="false" onAction="#switchToRules" text="Règles" />
                  <MenuItem mnemonicParsing="false" onAction="#exit" text="Quitter" />
               </items>
            </Menu>
            <Menu fx:id="about" mnemonicParsing="false" onShowing="#switchToAbout" text="À propos">
               <items>
<!--                THIS THE DUMMY MENU I USE TO BE ABLE TO TRIGGER THE EVENT ON THE PARENT -->
                  <MenuItem fx:id="dummyMenuItem" mnemonicParsing="false" />
               </items></Menu>
         </menus>
      </MenuBar>
   </top>
</BorderPane>

视图控制器的代码:

package org.HangmanGameFXViews.view;
import org.HangmanGameFXViews.Main;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.stage.Stage;

public class MenuesActionsControlleur {
    private Stage stageDialogue;
    private Main main;

    @FXML
    private Menu about;
    @FXML
    private MenuBar menusBar;
    @FXML
    private MenuItem dummyMenuItem;

    @FXML
    private void initialize() {

        about.addEventHandler(Event.ANY, new EventHandler<Event>() {

            @Override
            public void handle(Event event) {
                System.out.println("Showing Menu 1");
                System.out.println(event.getTarget().toString());
                System.out.println(event.getEventType().toString());

            }
        });
    }

    @FXML
    public void switchToRules() {
        main.switchToRules();
    }

    @FXML
    public void switchToAbout() {

        dummyMenuItem.setDisable(true);
        main.switchToAbout();
        dummyMenuItem.setDisable(false);

    }
    @FXML
    public void clickableMenu(ActionEvent e){
        System.out.println("Menu clicked");
    }

    @FXML
    public void switchToNew() {
        main.switchToNew();
    }
    @FXML
    public void switchToScore() {
        main.switchToScore();
    }

    public Stage getStageDialogue() {
        return stageDialogue;
    }

    public void setStageDialogue(Stage stageDialogue) {
        this.stageDialogue = stageDialogue;
    }

    @FXML
    public void exit() {
        stageDialogue.close();
    }

    public void setMainClass(Main m) {
        main = m;
        stageDialogue = main.getStagePrincipal();
    }
}

谢谢您的帮助。

user-interface javafx menu action
1个回答
0
投票
就是说:安装自定义处理程序的基本思想是在代表Menu的styleableNode上进行安装。默认情况下,仅当Menu是ContextMenu中的一项时才实现对该节点的访问,而不是由MenuBar中的MenuButton表示时才实现(我认为这是一个错误,但这是另一个故事)。

所以我们必须自己做

扩展菜单

    添加api设置包含菜单栏的对象
  • 实现getStyleableNode以访问MenuButton
  • 添加一些连线以重定向mouseReleased(或其他)触发菜单的动作
  • 自定义菜单可能有点类似(显然不是生产质量:):
  • public class MyMenu extends Menu { private MenuBar parentMenuBar; private Parent menuBarContainer; private MenuButton menuButton; private EventHandler<MouseEvent> redirector = this::redirect; public MyMenu(String string) { super(string); } public void setParentMenuBar(MenuBar menuBar) { this.parentMenuBar = menuBar; // tbd: cleanup if menuBar and/or its skin disposed/changed if (menuBar != null) { menuBar.skinProperty().addListener((src, ov, nv) -> { if (nv instanceof MenuBarSkin && menuBar.getChildrenUnmodifiable().size() == 1) { menuBarContainer = (Parent) menuBar.getChildrenUnmodifiable().get(0); menuBarContainer.getChildrenUnmodifiable().addListener((ListChangeListener)c -> { updateEventRedirector(); }); updateEventRedirector(); } }); } } protected void redirect(MouseEvent e) { // fire only if there are no items if (getItems().size() == 0) fire(); } /** * Rewire eventHandler when our styleable node is changed */ private void updateEventRedirector() { if (menuButton != null) { menuButton.removeEventHandler(MouseEvent.MOUSE_RELEASED, redirector); } menuButton = getParentMenuButton(); if (menuButton != null) { menuButton.addEventHandler(MouseEvent.MOUSE_RELEASED, redirector); } } @Override public Node getStyleableNode() { if (parentMenuBar != null && parentMenuBar.getChildrenUnmodifiable().size() == 1) { return menuButton; } return super.getStyleableNode(); } private MenuButton getParentMenuButton() { if (parentMenuBar == null || parentMenuBar.getChildrenUnmodifiable().size() != 1) return null; // beware: implementation detail of menuBarSkin! Parent parent = (Parent) parentMenuBar.getChildrenUnmodifiable().get(0); for (Node child : parent.getChildrenUnmodifiable()) { // beware: internal api! if (child instanceof MenuBarButton) { MenuBarButton menuButton = (MenuBarButton) child; if (menuButton.menu == this) { return menuButton; } } } return null; } }

    要使用:

    bar = new MenuBar();
    first = new MyMenu("dummy");
    first.setParentMenuBar(bar);
    first.setOnAction(e -> System.out.println("menu handler"));
    bar.getMenus().addAll(first, new Menu("other"));
    
  • © www.soinside.com 2019 - 2024. All rights reserved.