Skip to content

Instantly share code, notes, and snippets.

@Warlander
Last active December 23, 2021 13:59
Show Gist options
  • Save Warlander/815f5c435b2b11527ce65ff165dde023 to your computer and use it in GitHub Desktop.
Save Warlander/815f5c435b2b11527ce65ff165dde023 to your computer and use it in GitHub Desktop.
JavaFX clickable menu
import javafx.beans.property.StringProperty;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
public class ClickableMenu extends Menu {
private final Label label;
/**
* Creates new ClickableMenu without title.
*/
public ClickableMenu() {
this("");
}
/**
* Creates new ClickableMenu with given title.
* @param title initial title
*/
public ClickableMenu(String title) {
// dummy item is needed to make JavaFX "believe", that menu item was pressed
MenuItem dummyItem = new MenuItem();
dummyItem.setVisible(false);
getItems().add(dummyItem);
this.label = new Label();
label.setText(title);
label.setOnMouseClicked(evt -> {
// forced child MenuItem click (this item is hidden, so this action is not visible but triggers parent "onAction" event handler anyway)
dummyItem.fire();
});
setGraphic(label);
}
/**
* This method should be used instead of {@link #getText() getText()} method.
* @return title of this Menu
*/
public String getTitle() {
return label.getText();
}
/**
* This method should be used instead of {@link #setText() setText()} method.
* @param text new title of this menu
*/
public void setTitle(String text) {
label.setText(text);
}
/**
* This method should be used instead of {@link #textProperty() textProperty()} method.
* @return title property
*/
public StringProperty titleProperty() {
return label.textProperty();
}
}
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 MenuTest extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Direct menu item test");
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 800, 600);
root.prefHeightProperty().bind(scene.heightProperty());
primaryStage.setScene(scene);
MenuBar menuBar = new MenuBar();
root.setTop(menuBar);
Menu clickableMenu = createClickableMenu();
Menu normalMenu = createNormalMenu();
menuBar.getMenus().addAll(clickableMenu, normalMenu);
primaryStage.show();
}
private Menu createClickableMenu() {
ClickableMenu clickableMenu = new ClickableMenu("Clickable");
clickableMenu.setOnAction(evt -> System.out.println("Clickable item clicked"));
return clickableMenu;
}
private Menu createNormalMenu() {
Menu normalMenu = new Menu("File");
MenuItem saveItem = new MenuItem("Save");
saveItem.setOnAction(evt -> System.out.println("Save item clicked"));
MenuItem openItem = new MenuItem("Open");
openItem.setOnAction(evt -> System.out.println("Open item clicked"));
normalMenu.getItems().addAll(saveItem, openItem);
return normalMenu;
}
}
@IchZerowan
Copy link

Didn't work for me when used in .fxml. Neither using .setOnAction() nor via On Action in Scene Builder.
<MenuBar fx:id="aboutBar"> <menus> <ClickableMenu fx:id="miAbout" mnemonicParsing="false" onAction="#displayInfo" text="About" /> </menus></MenuBar>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment