Search code examples
javacssjavafx-8custom-controls

StyleableProperty in JavaFX CSS


I'm working on a custom control and am using the StyleablePropertyFactory to try and make a styleable property as follows:

private static final StyleablePropertyFactory<RackControl> FACTORY = new StyleablePropertyFactory<>(RackControl.getClassCssMetaData());
    private StyleableProperty<Color> defaultTubeColor = 
            FACTORY.createStyleableColorProperty(this, "defaultTubeColor", "-fx-default-tube-color", rc -> rc.defaultTubeColor);

I've then got getters and setters which allow me to access the read in value:

public Color getDefaultTubeColor() {
    return defaultTubeColor.getValue();
}

public void setDefaultTubeColor(Color defaultTubeColor) {
    System.out.println("Set default tube color");
    this.defaultTubeColor.setValue(defaultTubeColor);
}

@SuppressWarnings("unchecked")
public ObservableValue<Color> defaultTubeColorProperty() {

    return (ObservableValue<Color>) defaultTubeColor;
}

In the constructor I am setting a skin and style to look out for:

    this.setSkin(new RackControlSkin(this));
    getStyleClass().add("rack-control");

Then in my skin (though that doesn't really matter where I'm getting it from) I am trying to load in the css property as follows:

    System.out.println(control.getCssMetaData().stream().filter(c -> c.getProperty().equals("-fx-default-tube-color")).findFirst().get());
    System.out.println(control.getDefaultTubeColor());

This prints out:

CSSProperty {property: -fx-default-tube-color, converter: ColorConverter, initalValue: 0x000000ff, inherits: false, subProperties: []}
0x000000ff

So I know the property is being found from the following css file:

.rack-control {
   -fx-default-tube-color: red;
}

When it is being called from the scene as shown in my test code:

VBox root = new VBox();
RackControl control = new RackControl(8,12);
root.getChildren().addAll(control);
VBox.setVgrow(control, Priority.ALWAYS);
Scene scene = new Scene(root, 320, 200);
String css = this.getClass().getResource("rackcontrol.css").toExternalForm(); 
scene.getStylesheets().add(css);
//Scene scene = new Scene((Parent) FXMLLoader.load(getClass().getResource("TestUI.fxml")));
primaryStage.setTitle("Custom control");
primaryStage.setScene(scene);
primaryStage.show();

So as far as I can see; I'm doing everything correctly but the value just isn't being loaded in from the css file. Can anyone provide me with a pointer as to what I'm doing wrong here please?

Thanks, in advance, for reading the question and double thanks for any advice!

Cheers,

Neil


Solution

  • We found out the answer by deconstructing the meta classes - css properties are not set until after the constrcutor has been called. Therefore you need to set the skin up to listen to changes in the css and then do the drawing etc.