JavaFX 2.0 像 MenuItem 一样激活菜单
Posted
技术标签:
【中文标题】JavaFX 2.0 像 MenuItem 一样激活菜单【英文标题】:JavaFX 2.0 Activating a Menu like a MenuItem 【发布时间】:2012-04-25 12:37:31 【问题描述】:我正在制作一个MenuBar
,但我不想按下Menu
的功能,例如:“文件”,然后执行一个操作。比如打开另一个 fxml,或者写一些输出的例子。
我想要Menu
中的MenuItem
(谎言“关于”)的功能,例如“文件”。
package model;
import static java.lang.System.out;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/**
* Example of creating menus in JavaFX.
*
* @author Dustin
*/
public class JavaFxMenus extends Application
/**
* Build menu bar with included menus for this demonstration.
*
* @param menuWidthProperty Width to be bound to menu bar width.
* @return Menu Bar with menus included.
*/
private MenuBar buildMenuBarWithMenus(final ReadOnlyDoubleProperty menuWidthProperty)
final MenuBar menuBar = new MenuBar();
// Prepare left-most 'File' drop-down menu
final Menu fileMenu = new Menu("File");
menuBar.getMenus().add(fileMenu);
//menuBar.getOnMouseClicked().handle(this);
// Prepare 'Examples' drop-down menu
final Menu examplesMenu = new Menu("JavaFX 2.0 Examples");
examplesMenu.getItems().add(new MenuItem("Text Example"));
examplesMenu.getItems().add(new MenuItem("Objects Example"));
examplesMenu.getItems().add(new MenuItem("Animation Example"));
menuBar.getMenus().add(examplesMenu);
// Prepare 'Help' drop-down menu
final Menu helpMenu = new Menu("Help");
helpMenu.setOnAction(null);
final MenuItem searchMenuItem = new MenuItem("Search");
searchMenuItem.setDisable(true);
helpMenu.getItems().add(searchMenuItem);
final MenuItem onlineManualMenuItem = new MenuItem("Online Manual");
onlineManualMenuItem.setVisible(false);
helpMenu.getItems().add(onlineManualMenuItem);
helpMenu.getItems().add(new SeparatorMenuItem());
final MenuItem aboutMenuItem =
MenuItemBuilder.create()
.text("About")
.onAction(
new EventHandler<ActionEvent>()
@Override public void handle(ActionEvent e)
out.println("You clicked on About!");
)
.accelerator(
new KeyCodeCombination(
KeyCode.A, KeyCombination.CONTROL_DOWN))
.build();
helpMenu.getItems().add(aboutMenuItem);
menuBar.getMenus().add(helpMenu);
// bind width of menu bar to width of associated stage
menuBar.prefWidthProperty().bind(menuWidthProperty);
return menuBar;
/**
* Start of JavaFX application demonstrating menu support.
*
* @param stage Primary stage.
*/
@Override
public void start(final Stage stage)
stage.setTitle("Creating Menus with JavaFX 2.0");
final Group rootGroup = new Group();
final Scene scene = new Scene(rootGroup, 800, 400, Color.WHEAT);
final MenuBar menuBar = buildMenuBarWithMenus(stage.widthProperty());
rootGroup.getChildren().add(menuBar);
stage.setScene(scene);
stage.show();
/**
* Main executable function for running examples.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
Application.launch(arguments);
【问题讨论】:
【参考方案1】:AFAIK, A Menu
,如果没有添加任何子菜单或Menuitem
s,则不会在单击、显示或隐藏时触发事件。然而,解决方法是设置它的图形,例如,这个图形节点将处理鼠标点击,
Label menuLabel = new Label("File");
menuLabel.setOnMouseClicked(new EventHandler<MouseEvent>()
@Override
public void handle(MouseEvent event)
Stage myDialog = new Stage();
myDialog.initModality(Modality.WINDOW_MODAL);
Scene myDialogScene = new Scene(VBoxBuilder.create()
.children(new Text("Hello! it's My Dialog."))
.alignment(Pos.CENTER)
.padding(new Insets(10))
.build());
myDialog.setScene(myDialogScene);
myDialog.show();
);
Menu fileMenuButton = new Menu();
fileMenuButton.setGraphic(menuLabel);
menuBar.getMenus().add(fileMenuButton);
这种方法的一个缺点是标签没有覆盖菜单的所有空间,导致单击菜单边缘不会触发鼠标事件。通过取消注释上面的menuLabel.setStyle
来查看这一点。但这可以通过我认为的 CSS
样式来解决。
代码部分取自Create Dialog using Stage。您还可以使用FXMLLoader
将FXML
文件加载到myDialog
阶段。网上有很多关于它的例子。
【讨论】:
【参考方案2】:最近我也遇到了同样的问题,我就是这样做的
@FXML private Menu myMenu;
@Override
public void initialize(URL url, ResourceBundle rb)
myMenu.setGraphic(
ButtonBuilder.create()
.text("btnText")
.onAction(new EventHandler<ActionEvent>()
@Override public void handle(ActionEvent t)
//TODO
)
.build()
);
【讨论】:
【参考方案3】:结合我们朋友@Dota2的回答,我构建了一个帮助类来触发Menu
的onAction(Menu menu)
事件,即使它里面没有任何MenuItem
。这是静态辅助方法:
public static void onAction(Menu menu)
final MenuItem menuItem = new MenuItem();
menu.getItems().add(menuItem);
menu.addEventHandler(Menu.ON_SHOWN, event -> menu.hide());
menu.addEventHandler(Menu.ON_SHOWING, event -> menu.fire());
然后你调用:
YourHelperClass.onAction(myMenu);
准备好了!我希望这会有所帮助。
【讨论】:
【参考方案4】:最近我遇到了同样的问题,这是我的出路:
我在菜单中有一个 menuItem,它的行为就像单击了 menuItem(在您的情况下为 File
菜单)。所以你可以做的是有一个 menuItem Dummy_menuItem
final Menu fileMenu = new Menu("File");
fileMenu.getItems().add(new MenuItem("Dummy_menuItem"));
menuBar.getMenus().add(fileMenu);
然后单击File
菜单,触发Dummy_menuItem
menuItem 或您希望拥有的任何功能。为了确定哪个菜单应该有这个属性,我使用numberOfMenuItems
来获取menubar 中菜单中menuItems 的数量
if (numberOfMenuItems == 1)
menu.showingProperty().addListener(
(observableValue, oldValue, newValue) ->
if (newValue)
// the first menuItem is triggered
menu.getItems().get(0).fire();
);
结果是Dummy_menuItem
被触发,而没有在单击File
菜单或任何具有一个menuItem 的菜单时显示menuItem 的上下文。所以看起来好像您单击了File
菜单并被重定向到另一个页面或其他什么。
希望这会有所帮助!
【讨论】:
这很完美,应该是公认的答案。无需修改图形,使用showingProperty
即可。
不幸的是,如果您将菜单与 1 个子项和 1 个以上子项组合在一起,这将不起作用。鼠标悬停在一个子菜单上,鼠标悬停触发,无需点击鼠标【参考方案5】:
我认为您不能允许对主菜单标签执行任何操作。
但是,您可以创建一个堆栈窗格,并用文本和菜单栏填充它。
【讨论】:
以上是关于JavaFX 2.0 像 MenuItem 一样激活菜单的主要内容,如果未能解决你的问题,请参考以下文章
从另一个场景切换启用/禁用 MenuItem javafx?
JavaFX MenuItem.setAccelerator() 不工作
为啥JavaFX Scene Builder打开失败,版本1.1和2.0都一样