I want to have a special style class for a ComboBox that I could reuse. For example, I want to create a class yellowed
that will provide yellow background. This is my code:
Java:
public class NewMain extends Application {
@Override
public void start(Stage primaryStage) {
ComboBox<String> comboBox = new ComboBox<>();
comboBox.getItems().addAll("Option 1", "Option 2", "Option 3");
comboBox.getStyleClass().add("yellowed");
VBox vbox = new VBox(comboBox);
Scene scene = new Scene(vbox, 400, 300);
scene.getStylesheets().add(NewMain.class.getResource("test.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
CSS:
.combo-box.yellowed {
-fx-background-color: yellow;
}
.combo-box-popup.yellowed > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell {
-fx-background-color: yellow;
}
The problem is that the popup (of my ComboBox with yellowed
style class) that will be shown won't have a yellowed
class.
Could anyone say, if there is a way to add a style class to the popup of a specific ComboBox?
The popup is considered a descendant of the ComboBox
1. This is documented by the JavaFX CSS Reference Guide:
ComboBox
Style class: combo-box
The ComboBox control has all the properties and pseudo‑classes of ComboBoxBase
Substructure
- list-cell — a ListCell instance used to show the selection in the button area of a non-editable ComboBox
- text-input — a TextField instance used to show the selection and allow input in the button area of an editable ComboBox
- combo-box-popup — a PopupControl that is displayed when the button is pressed [emphasis added]
- list-view — a ListView
- list-cell — a ListCell
So, all you need to do is:
.combo-box.yellowed .combo-box-popup .list-cell {
-fx-background-color: yellow;
}
Technically, combo-box.yellowed .list-cell
is sufficient, but note that will also target the node used to display the actual combo box (i.e., the "button cell", which is also a ListCell
). And of course you can make the selector more specific if you want/need to.
Here's a runnable example:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
// Text blocks require Java 15+
private static final String STYLESHEET =
"""
.combo-box.yellow,
.combo-box.yellow .combo-box-popup .list-cell {
-fx-background-color: yellow;
}
.combo-box.red,
.combo-box.red .combo-box-popup .list-cell {
-fx-background-color: red;
}
""";
@Override
public void start(Stage primaryStage) {
var box1 = createComboBox();
box1.getStyleClass().add("yellow");
var box2 = createComboBox();
box2.getStyleClass().add("red");
var root = new HBox(10, box1, box2);
root.setAlignment(Pos.CENTER);
var scene = new Scene(root, 500, 300);
// Adding stylesheet via data URI requires JavaFX 17+
scene.getStylesheets().add("data:text/css," + STYLESHEET);
primaryStage.setScene(scene);
primaryStage.show();
}
private ComboBox<String> createComboBox() {
var box = new ComboBox<String>();
for (int i = 1; i <= 5; i++) {
box.getItems().add("Option #" + i);
}
// The 'getFirst' method requires Java 21+
box.setValue(box.getItems().getFirst());
return box;
}
public static void main(String[] args) {
launch(Main.class);
}
}
Note the example, as written, requires Java 21+ and JavaFX 17+.
1. For the curious, this is implemented by overriding PopupControl#getStyleableParent()
to return the control.