我正在尝试使用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();
}
}
谢谢您的帮助。
所以我们必须自己做
扩展菜单
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"));