Is it possible to change css for a JavaFX application while it is running?
The effect I am looking for is changing skins or themes at the click of a button.
The UI is in an FXML
file if that makes any difference.
I have tried
Scene.getStylesheets()
.add(getClass().getResource(skinFileName).toExternalForm());
which has no effect.
thanks
It should have the effect. Try this full demo code:
public class CssThemeDemo extends Application {
private String theme1Url = getClass().getResource("theme1.css").toExternalForm();
private String theme2Url = getClass().getResource("theme2.css").toExternalForm();
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
final Scene scene = new Scene(root, 300, 250);
System.out.println("scene stylesheets: " + scene.getStylesheets());
scene.getStylesheets().add(theme1Url);
System.out.println("scene stylesheets: " + scene.getStylesheets());
final Button btn = new Button("Load Theme 1");
btn.getStyleClass().add("buttonStyle");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
scene.getStylesheets().remove(theme2Url);
System.out.println("scene stylesheets on button 1 click: " + scene.getStylesheets());
if(!scene.getStylesheets().contains(theme1Url)) scene.getStylesheets().add(theme1Url);
System.out.println("scene stylesheets on button 1 click: " + scene.getStylesheets());
}
});
final Button btn2 = new Button("Load Theme 2");
btn2.getStyleClass().add("buttonStyle");
btn2.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
scene.getStylesheets().remove(theme1Url);
System.out.println("scene stylesheets on button 2 click: " + scene.getStylesheets());
if(!scene.getStylesheets().contains(theme2Url)) scene.getStylesheets().add(theme2Url);
System.out.println("scene stylesheets on button 2 click: " + scene.getStylesheets());
}
});
ComboBox<String> comboBox = new ComboBox<String>(FXCollections.observableArrayList("Just", "another", "control"));
root.getChildren().add(VBoxBuilder.create().spacing(10).children(btn, btn2, comboBox).build());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
theme1 css:
.root{
-fx-font-size: 14pt;
-fx-font-family: "Tahoma";
-fx-base: #DFB951;
-fx-background: #A78732;
-fx-focus-color: #B6A678;
}
.buttonStyle {
-fx-text-fill: #006464;
-fx-background-color: #DFB951;
-fx-border-radius: 20;
-fx-background-radius: 20;
-fx-padding: 5;
}
theme2 css:
.root{
-fx-font-size: 16pt;
-fx-font-family: "Courier New";
-fx-base: rgb(132, 145, 47);
-fx-background: rgb(225, 228, 203);
}
.buttonStyle {
-fx-text-fill: red;
-fx-background-color: lightcyan;
-fx-border-color: green;
-fx-border-radius: 5;
-fx-padding: 3 6 6 6;
}
Note the same named CSS selectors in both theme1 and theme2 css files.