Reputation: 8363
I have looked at a few JavaFX classes related to menu, but I could not find what I want. I want to implement something that works like a MenuBar
, except that I want it to open its menu on hover, not on click. While I can definitely build something from scratch on my own, it would be a waste of time if there is already something that allows me to do something similar to that. Anyone knows how do I do that?
Upvotes: 0
Views: 2275
Reputation: 2917
Well it is possible to make it if you use the lookup()
. You can easily take the container holding the Menus and then apply on them the setOnMouseEntered()
or setOnMouseExited()
to catch mouse events on each Menu.
Here is an example :
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
MenuBar menuBar = new MenuBar();
Menu editMenu = new Menu("File");
MenuItem fileMenuItem1 = new MenuItem("Item 1");
MenuItem fileMenuItem2 = new MenuItem("Item 2");
MenuItem fileMenuItem3 = new MenuItem("Item 3");
editMenu.getItems().addAll(fileMenuItem1, fileMenuItem2, fileMenuItem3);
Menu fileMenu = new Menu("Edit");
MenuItem fileMenu1 = new MenuItem("Item 1");
MenuItem fileMenu2 = new MenuItem("Item 2");
MenuItem fileMenu3 = new MenuItem("Item 3");
fileMenu.getItems().addAll(fileMenu1, fileMenu2, fileMenu3);
menuBar.getMenus().addAll(editMenu, fileMenu);
mainPane.setTop(menuBar);
Scene scene = new Scene(mainPane, 300, 300);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
// Find menubar HBox holding the menus
HBox container = (HBox) menuBar.lookup("HBox");
for(int i = 0 ; i < container.getChildren().size() ; i++) {
Node parentNode = container.getChildren().get(i);
Menu menu = menuBar.getMenus().get(i);
parentNode.setOnMouseMoved(e->{
menu.show();
});
}
}
public static void main(String[] args) {
launch(args);
}
}
You might wonder why i use the setOnMouseMoved
instead of setOnMouseEntered
. Well that's because the setOnMouseEntered
creates a strange behavior while moving the mouse between menus and the usage of setOnMouseMoved
fix it.
In addition in case you wondering how did I know to use the lookup("HBox")
the truth is my first attempt was System.out.println( menuBar.lookupAll("*"));
which gave me the current informations :
[MenuBar@5e57a6ce[styleClass=menu-bar], HBox@13ccf856[styleClass=container], MenuBarSkin$MenuBarButton[id=null, styleClass=menu-button menu]'File', MenuButtonSkinBase$MenuLabeledImpl@25917f7f[styleClass=label]'File', Text[text="File", x=0.0, y=0.0, alignment=LEFT, origin=BASELINE, boundsType=LOGICAL_VERTICAL_CENTER, font=Font[name=System Regular, family=System, style=Regular, size=12.0], fontSmoothingType=LCD, fill=0x333333ff], StackPane@c341eae[styleClass=arrow-button], StackPane@7b8501c0[styleClass=arrow], MenuBarSkin$MenuBarButton[id=null, styleClass=menu-button menu]'Edit', MenuButtonSkinBase$MenuLabeledImpl@4d8224b7[styleClass=label]'Edit', Text[text="Edit", x=0.0, y=0.0, alignment=LEFT, origin=BASELINE, boundsType=LOGICAL_VERTICAL_CENTER, font=Font[name=System Regular, family=System, style=Regular, size=12.0], fontSmoothingType=LCD, fill=0x333333ff], StackPane@3d75fcac[styleClass=arrow-button], StackPane@71f02eed[styleClass=arrow]]
Upvotes: 1
Reputation: 88
I think you are looking for class javafx.scene.control.ContextMenu
and the method show(Node anchor, double screenX, double screenY)
Upvotes: 0