Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Menu Item Hover become Hand JavaFX

Tags:

javafx

How to make cursor click become hand when hover on menuItem?

Because there is no setOnMouse or setCursor methods on menu item.

This is my code

private void handleAction() {
    loginBtn.setCursor(Cursor.HAND);
    loginBtn.setOnAction(e -> {
        String email = emailTf.getText();
        String password = passTf.getText();
        
        MsUser user = validateUser(email, password);
        if (user != null) {
            openHome();
            System.out.println("Open Home");
        } else {
            Alert alert = new Alert(AlertType.ERROR);
            alert.setTitle("Login Failed");
            alert.setHeaderText("Error");
            alert.setContentText("Wrong credentials");
            alert.showAndWait();
        }
    });
    
    signupLbl.setCursor(Cursor.HAND);
    signupLbl.setOnMouseEntered(e-> signupLbl.setTextFill(Color.DARKBLUE));
    signupLbl.setOnMouseExited(e -> signupLbl.setTextFill(Color.BLUE));
    signupLbl.setOnMouseClicked(e -> openRegister());
    
    
    registerMenu.setOnAction(e -> openRegister());
}
like image 381
Wahyu Imam Prasetyo Avatar asked Sep 21 '25 04:09

Wahyu Imam Prasetyo


1 Answers

You can use CSS for this:

import javafx.application.Application;
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.stage.Stage;

public class Main extends Application {

  // Note: Text blocks require Java 15+.
  private static final String STYLEHSEET =
      """
      .menu-bar .menu-item {
        -fx-cursor: hand;
      }
      """;

  @Override
  public void start(Stage primaryStage) {
    var item = new MenuItem("Menu item");

    var menu = new Menu("Menu");
    menu.getItems().add(item);

    var root = new BorderPane();
    root.setTop(new MenuBar(menu));

    var scene = new Scene(root, 300, 150);

    // Note: Adding stylesheets as a Data URI requires JavaFX 17+.
    scene.getStylesheets().add("data:text/css," + STYLEHSEET);

    primaryStage.setScene(scene);
    primaryStage.show();
  }

  public static void main(String[] args) {
    launch(Main.class);
  }
}

Note the CSS is defined in a string to make running the example easier. In a real application, it would be better to separate the CSS into its own *.css file.

Unfortunately, setting the -fx-cursor property with item.setStyle(...) didn't seem to work for me using JavaFX 23.0.1. Though the following programmatic approach seems to work:

// Note: Using '_' for unused parameters requires Java 22+.
menu.setOnShown(_ -> {
  for (var item : menu.getItems()) {
    item.getStyleableNode().setCursor(Cursor.HAND);
  }
});

To avoid unnecessary work, you could remove the onShown handler after it executes. The reason for doing this work in the onShown handler, by the way, is because getStyleableNode() returns null if the menu item hasn't been displayed at least once.

like image 52
Slaw Avatar answered Sep 23 '25 13:09

Slaw