We can create custom menu easily in JavaFX using CustomMenuItem class. I was thinking that using that class, I can creat menu separator that has label. What I want to use with that was to group menu items. Each group should have label name using the menu separator. So, I created a component namely LabelSeparator that will fill CustomMenuItem.
public class LabelSeparator extends StackPane {
private Label lblText;
public LabelSeparator(String label) {
this(label, true);
}
public LabelSeparator(String label, boolean topPading) {
HBox line = HBoxBuilder.create()
.styleClass("line")
.minHeight(2)
.prefHeight(2)
.prefWidth(USE_PREF_SIZE)
.maxHeight(USE_PREF_SIZE)
.build();
if (topPading) {
setPadding(new Insets(10, 0, 0, 0));
}
lblText = LabelBuilder.create().text(label).build();
this.getChildren().addAll(line, lblText);
this.getStyleClass().add("label-separator");
}
public void setText(String label) {
textProperty().set(label);
}
public String getText() {
return textProperty().get();
}
public StringProperty textProperty() {
return lblText.textProperty();
}
}
But when I used that class to fill CustomMenuItem and added it to ContextMenu, the menu item didn’t fill horizontally as I expected. It also still received blue-background when hovered. I checked the source code of SeparatorMenuItem, but I found no clues. I checked deeper by searching what classes use SeparatorMenuItem. I found that there are many line of
if (item instanceof SeparatorMenuItem) {
...
}
I came to a conclusion that SeparatorMenuItem is treated differently.
So I changed my approach. I created a class extending SeparatorMenuItem so it will be treated as one.
public class LabelSeparatorMenuItem extends SeparatorMenuItem {
public LabelSeparatorMenuItem(String label) {
this(label, true);
}
public LabelSeparatorMenuItem(String label, boolean topPading) {
super();
LabelSeparator content = new LabelSeparator(label, topPading);
content.setPrefHeight(LabelSeparator.USE_COMPUTED_SIZE);
content.setMinHeight(LabelSeparator.USE_PREF_SIZE);
setContent(content);
}
}
Nice, It worked as expected. The separator filled horizontally and it ignored mouse events.

The CSS for LabelSeparator is below
.label-separator .line {
-fx-border-color: derive(-fx-background, -25%) -fx-background derive(-fx-background, 40%) -fx-background;
}
.label-separator .label {
-fx-background-color:
#090a0c,
linear-gradient(#38424b 0%, #1f2429 20%, #191d22 100%),
linear-gradient(#20262b, #191d22),
radial-gradient(center 50% 0%, radius 100%, rgba(114,131,148,0.9), rgba(255,255,255,0));
-fx-background-radius: 5,4,3,5;
-fx-background-insets: 0,1,2,0;
-fx-text-fill: white;
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
-fx-font-family: "Arial";
-fx-text-fill: linear-gradient(white, #d0d0d0);
-fx-font-size: 12px;
-fx-padding: 2 10;
}