Search code examples
javacssjavafxjfoenixjavafx-css

How can I change the color of a JFXSlider's thumb according to the color of the slider at the current position of the thumb on the slider?


I'm using a JFXSlider in JavaFX and I've used a linear gradient for the color of the JFXSlider's track (with CSS). However, I'd also like to change the color of the thumb to that of the slider for that position. I've used the following CSS for the slider's linear gradient and for getting rid of the default green color of the JFXSlider:

.jfx-slider .track {
    -fx-pref-height: 10;
    -fx-background-color: linear-gradient(to right,red,orange);
}
.jfx-slider .colored-track {
    -fx-background-color: transparent;
}

I tried the following CSS code to get the thumb color to be the same as that of the slider at the current position, but it didn't work.

.jfx-slider .thumb {
    -fx-background-color: linear-gradient(to right,red,orange);
}

I guess it's probably that the code I tried only provides an internal linear gradient for the thumb's background color. Does anyone know how to solve this problem? P.S. I'm using JFoenix 9.0.10, JavaFX 15, and JDK 15.


Solution

  • One possible solution would be to add a global CSS variable and change it depending on the JFXSlider current value. For example :

    .root {
        -fx-custom-color : red;
    }
    

    And then use this variable on your jfx-slider css rules like :

    /* Styling the slider thumb */
    .jfx-slider>.thumb {
        -fx-background-color: -fx-custom-color;
    }
    
    /* Styling the animated thumb */
    .jfx-slider>.animated-thumb {
        -fx-background-color: -fx-custom-color;
    }
    

    After that, you need to figure out how to update the "-fx-custom-color" variable and how to determine which color you need to set for the specific value of the Slider (or rather location).

    First, you should add a listener to the value property to listen for value changes. Second, use the interpolate method of the Color class to determine the color, and finally, update the new value for the -fx-custom-color using inline CSS style to the JFXSlider.

    Here is a complete example :

    import com.jfoenix.controls.JFXSlider;
    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    
    public class SliderTesting extends Application {
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
    
            JFXSlider slider = new JFXSlider(0, 100, 0);
    
            slider.valueProperty().addListener(e -> {
                Color imageColor = Color.RED.interpolate(Color.ORANGE,
                        slider.getValue() / 100);
                slider.setStyle("-fx-custom-color : " + colorToHex(imageColor) + ";");
            });
    
            VBox box = new VBox(slider);
            box.setPadding(new Insets(20));
            box.setPrefSize(400, 400);
            box.setAlignment(Pos.CENTER);
    
            Scene scene = new Scene(box);
            scene.getStylesheets()
                    .add(this.getClass().getResource("custom-jfoenix.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static String colorToHex(Color color) {
            return String.format("#%02X%02X%02X", (int) (color.getRed() * 255),
                    (int) (color.getGreen() * 255), (int) (color.getBlue() * 255));
        }
    }
    

    And the "custom-jfoenix.css" file

    .root {
        -fx-custom-color : red;
    }
    
    /* Styling the slider track */
    .jfx-slider>.track {
        -fx-pref-height: 10;
    }
    
    /* Styling the slider thumb */
    .jfx-slider>.thumb {
        -fx-background-color: -fx-custom-color;
    }
    
    /* Styling the filled track */
    .jfx-slider>.colored-track {
        -fx-background-color: linear-gradient(to right, red, orange);
    }
    
    /* Styling the animated thumb */
    .jfx-slider>.animated-thumb {
        -fx-background-color: -fx-custom-color;
    }
    

    And the result :

    enter image description here