Jai
Jai

Reputation: 8363

A Menu that triggers purely on hover in JavaFX?

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

Answers (2)

JKostikiadis
JKostikiadis

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

Happy
Happy

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

Related Questions