Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically change JavaFX css property

Tags:

java

css

javafx

In my FXML I have a simple slider:

<Slider fx:id="timeSlider" showTickLabels="true" GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="4"/>

This slider is part of a desktop music application I am writing and it signifies how far into the song has been played. I have written a change event that is called everytime the the song time is changed, and this successfully accomplishes sliding the knob/thumb down.

Now I am trying to also to color the left part (already played) blue and the right part (yet to be played) white as the knob slides down. If I hard code this line into my CSS i can accomplish fading from blue/white at the 50% mark.

.slider .track {-fx-background-color: linear-gradient(to right, #90C7E0 50%, white 50%);}

However, I need this to be dynamic based on how far I am in the song. I have written the following code, but can't seem to get the CSS style to apply

song.getMediaPlayer().currentTimeProperty().addListener(new ChangeListener<Duration>() {
        @Override
        public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
            if (newValue != null && timeSlider != null) {
                timeSlider.setValue(newValue.toSeconds());
                double percentage = (newValue.toSeconds()/song.getDuration())*100;
                String css = ".slider .track{-fx-background-color: linear-gradient(to right, #90C7E0 " +
                 percentage + "%, white " + percentage + "%);}";
                timeSlider.getStyleClass().add(css);
            }
        }
    });

I believe it's something to do with how I am adding the CSS as a style, because even adding a simple non dynamic style does not work. I get no errors so I am not sure what I am doing wrong.

Any help is appreciated, and better ways to accomplish this are also appreciated. Thanks!

like image 826
Ashley Avatar asked Mar 06 '23 03:03

Ashley


1 Answers

The method getStyleClass() returns a list of CSS class names associated with the node. These class names are used to determine which rules in an external CSS file are applied to the node. You cannot pass CSS selectors and rules in here.

Instead, write an external CSS file which contains a rule for the background color for the track. You can use a "looked-up color" here, which basically works like a "CSS variable". Define the "looked-up color" for the slider, and use it in a rule for the track to set the background color:

style.css:

.slider {
    -track-color: white ;
}
.slider .track {
    -fx-background-color: -track-color ;
}

Now, in the Java code, you can update the value for the looked-up color by calling setStyle("-track-color: /* someColor */") on the slider. Here is a quick example:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SliderTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Slider slider = new Slider();
        slider.valueProperty().addListener((obs, oldValue, newValue) -> {
            double percentage = 100.0 * (newValue.doubleValue() - slider.getMin()) / (slider.getMax() - slider.getMin());
            slider.setStyle("-track-color: linear-gradient(to right, #90C7E0 " + percentage+"%, white "+percentage+("%);"));
        });
        StackPane root = new StackPane(slider);
        root.setPadding(new Insets(20));
        Scene scene = new Scene(root);
        scene.getStylesheets().add("style.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

In your application, you can do the same using the current time of the media player (or just register a listener on the slider's value property, as that is changing too).

like image 177
James_D Avatar answered Mar 16 '23 01:03

James_D