Is it possible to set a JavaFX static property in CSS?
For JavaFX versions 2.0 to 2.2 => no you cannot set the static layout properties via css.
You can create a feature request in the JavaFX jira to ask this functionality be implemented in a future JavaFX version.
StyleableProperty in JavaFX CSS
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.
Dynamically change JavaFX css property
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).
JavaFx: CSS element unable to inherit properties of it's ID
There is no need to set non-JavaFX CSS attributes like font
rather than -fx-font
, those non-JavaFX CSS attributes will just be ignored (or potentially cause issues).
If you set the font in the FXML (not recommended), then I think that would override the value you set in CSS usually.
Generally, for styles like titles, it is probably best to use a style class rather than an id.
I don't think using the *
universal selector is a good idea. Maybe it is OK, maybe it is not. The standard JavaFX modena.css
style sheet uses a syntax of .root
for the defaults, perhaps that would be better for you.
A description of the root
style class in the Scene
JavaFX CSS:
The Scene object has no settable CSS properties, nor does it have any pseudo‑classes. However, the root node of the scene is assigned the style class "root" (in addition to style classes already assigned to the node). This is useful because the root node of Scene is the root container for all active scene‑graph nodes. Thus, it can serve as a container for properties that are inherited or looked up.
Also, you tagged your question javafx-8. JavaFX 8 is obsolete, and a more modern version of JavaFX is recommended.
Changing default colors
If you want to change the default colors for the application, then you can do that by overriding the looked-up colors defined in the .root
section of the default modena.css
stylesheet.
The main looked-up color which you might override is -fx-base
which sets the default color style for the entire application.
Study the JavaFX CSS reference if you would like to learn more about looked-up colors.
For example, the following style sheet rule sets the default font size to 20 and the default color of the text in labels to dark green.
.root {
-fx-font-size: 20;
-fx-text-background-color: darkgreen;
}
Example App
The example defines a default size for text in the app within the .root
section. The default style size is overridden in the .title
section so that titles can be larger. The example application requires JavaFX 17+.
The example application doesn't set default colors, but, if you want to do that, you can experiment by changing the supplied CSS to match the CSS in the default colors section of the answer.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class RootFontSizeApp extends Application {
public static final String CSS = "data:text/css," + // language=CSS
"""
.root {
-fx-font-size: 20;
}
.title {
-fx-font-size: 30;
}
""";
@Override
public void start(Stage stage) throws Exception {
Label title = new Label("Greetings earthlings");
title.getStyleClass().add("title");
Scene scene = new Scene(
new VBox(20,
title,
new Label("hello, world")
)
);
scene.getStylesheets().setAll(CSS);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Declaring Variable In JavaFX CSS File
Unfortunately it seems to work only for colors. But you need to ensure that your variable is "visible" from rule which uses it:
* {
-fx-base2: #e00;
}
.track {-fx-background-color: -fx-base2;}
How to set several default CSS stylesheet for an application with JavaFX 9 (a replace for StyleManager)?
It's just another lack of JavaFX - simply use the JVM parameter below to make the StyleManager accessible.
--add-exports=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED
JavaFX Custom Control CSS PseudoClass state change stroke color
You only ever apply the color/stoke width at the time you create the skin.
You need to listen/bind to the stylable properties instead:
strokeColorProperty = control.strokeColorProperty();
strokeWidthProperty = control.strokeWidthProperty();
How to change the style of components by their attributes?
If I would change the text it would also automatically change the
style
Option 1: control style by id
You can achieve it by using a custom label that changes style when changing text. I'll demonstrat it by changing the label's id. This simplified example uses the text as id :
import javafx.geometry.Pos;
import javafx.scene.control.Label;
public class CustomLabel extends Label{
public CustomLabel() {
setAlignment(Pos.CENTER);
setPrefSize(50, 25);
}
void setTextAndId(String s){
super.setText(s);
/*To keep this demo simple and clear id is changed.
If used, care must be taken to keep id unique.
Using setStyle() or PseudoClass should be preferred
*/
setId(s);
}
}
The custom label can be used in an fxml (Root.fxml
):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>
<?import tests.CustomLabel?>
<StackPane fx:id="root" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="tests.Controller">
<children>
<CustomLabel fx:id="cLabel" text="""" />
</children>
</StackPane>
A simple css that changes background color based on id (Root.css
):
#1{
-fx-background-color: red;
-fx-text-fill: white;
}
#2{
-fx-background-color: yellow;
-fx-text-fill: red;
}
#3{
-fx-background-color: green;
-fx-text-fill: yellow;
}
Test class:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class LabelCssTest extends Application {
@Override public void start(Stage stage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Root.fxml"));
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And test controller :
import javafx.animation.PauseTransition;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.util.Duration;
public class Controller {
@FXML
CustomLabel cLabel;
@FXML Parent root;
private static final int MIN_VALUE = 1, MAX_VALUE = 3;
private int counter = MIN_VALUE;
@FXML
private void initialize() {
root.getStylesheets().add(getClass().getResource("Root.css").toExternalForm());
cLabel.setTextAndId(String.valueOf(counter++));
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(event ->{
cLabel.setTextAndId(String.valueOf(counter++));
if(counter > MAX_VALUE) {
counter = MIN_VALUE;
}
pause.play();
});
pause.play();
}
}
Option 2: control style by changing style-class
Use the same test class as option 1.
Root.fxml
:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>
<StackPane fx:id="root" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tests.Controller">
<children>
<Label fx:id="label" alignment="CENTER" contentDisplay="CENTER" prefHeight="20.0" prefWidth="70.0" text="" "" />
</children>
</StackPane>
Root.css
:
.style1{
-fx-background-color: red;
-fx-text-fill: white;
}
.style2{
-fx-background-color: yellow;
-fx-text-fill: red;
}
.style3{
-fx-background-color: green;
-fx-text-fill: yellow;
}
And controller:
import javafx.animation.PauseTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.util.Duration;
public class Controller {
@FXML Label label;
@FXML Parent root;
private static final int MIN_VALUE = 1, MAX_VALUE = 3;
private SimpleIntegerProperty counter = new SimpleIntegerProperty();
@FXML
private void initialize() {
root.getStylesheets().add(getClass().getResource("Root.css").toExternalForm());
counter = new SimpleIntegerProperty();
counter.addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
label.getStyleClass().clear();
label.getStyleClass().add("style"+counter.get());
});
label.textProperty().bind(Bindings.createStringBinding(()->String.valueOf(counter.get()), counter));
counter.set(1);
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(event ->{
counter.set(counter.get() >= MAX_VALUE ? MIN_VALUE : counter.get()+1);
pause.play();
});
pause.play();
}
}
Option 3: control style by using PseudoClass
:
Changes from option 2: Root.css
:
.root:style1 #label{
-fx-background-color: red;
-fx-text-fill: white;
}
.root:style2 #label{
-fx-background-color: yellow;
-fx-text-fill: red;
}
.root:style3 #label{
-fx-background-color: green;
-fx-text-fill: yellow;
}
And controller:
import javafx.animation.PauseTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.css.PseudoClass;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.util.Duration;
public class Controller {
@FXML Label label;
@FXML Parent root;
private static final int MAX_VALUE = 3;
private SimpleIntegerProperty counter = new SimpleIntegerProperty(1);
@FXML
private void initialize() {
root.getStylesheets().add(getClass().getResource("Root.css").toExternalForm());
counter = new SimpleIntegerProperty();
counter.addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
updateStates();
});
label.textProperty().bind(Bindings.createStringBinding(()->String.valueOf(counter.get()), counter));
counter.set(1);
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(event ->{
counter.set(counter.get() >= MAX_VALUE ? 1 : counter.get()+1);
pause.play();
});
pause.play();
}
private void updateStates() {
for( int index = 1; index <= MAX_VALUE; index++){
PseudoClass pc = PseudoClass.getPseudoClass("style"+String.valueOf(index));
root.pseudoClassStateChanged(pc, index == counter.get() ? true : false);
}
}
}
Javafx - change Theme (CSS) on active window
Css file can be changed on the run without reloading or setting a new stage
replacing the styleSheet with set()
method for observableList
App.java
public class App extends Application {
@Override
public void start(Stage stage) {
Button button = new Button("change");
button.setOnAction(e ->button.getScene().getStylesheets().set(0, "1.css"));
Button button1 = new Button("default");
button1.setOnAction(e ->button.getScene().getStylesheets().set(0, "0.css"));
HBox hBox = new HBox(button,button1);
AnchorPane anchorPane =new AnchorPane(hBox);
anchorPane.getStyleClass().add("pane");
var scene = new Scene(anchorPane, 640, 480);
scene.getStylesheets().add("0.css");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
0.css
.pane{
-fx-background-color:cyan;
}
1.css
.pane{
-fx-background-color:orange;
}
JavaFX CSS root property reference not resolved
It appears the issue here is that the stylesheet (caspian.css) is lazily loaded. Therefore, unless a component is constructed (not even necessarily added) the stylesheet is not resolved. Layout containers (like AnchorPane) do not trigger loading of the stylesheet. On the other hand, Controls (like Button/CheckBox/Label etc.) will trigger the stylesheet to be loaded.
Here is an updated version of the test case above to illustrate this behavior:
public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
AnchorPane pane = new AnchorPane();
new Button(); // Trigger loading of default stylesheet
Scene s = new Scene(pane, 800, 600);
pane.getStylesheets().add("test.css");
pane.getStyleClass().add("test");
System.out.println("Root pane style classes:");
for (String clazz : pane.getStyleClass())
System.out.println(clazz);
stage.setScene(s);
stage.show();
}
public static void main(String[] args) {
Application.launch();
}
}
Related Topics
Media Query in Responsive Email Template
Why Is Google Font Weight Not Working
Apply External CSS to Specific Area
Vertically Center a Div with Variable Height Within a Div That Is 100% of The Viewport
Which Browsers Still Support CSS Expressions
Overflow with Absolute/Relative Positioning Layout
How to Apply a CSS Stylesheet to All Page Views in My Firefox Browser
How to Disable Inline CSS in Gatsby
Why Won't My Visited Link Have a Background Color
How to Add Background Image in CSS