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; }