Reputation: 708
I have a JavaFX FXML scene with an number of circle shapes. Each circle represents a light bulb. A light bulb is turned on when it has a certain JavaFX CSS class, say "lightOn", otherwise it is off. The CSS defines the appearance of the circle so that it appear shining when it has the "lightOn" class, and dimmed when it has no class.
I also have a plain Java object as model which holds a collection of Boolean values. Each boolean value belongs to an individual light bulb of the view and indicates whether the light is on or off.
How can connect the style class of the individual "light bulbs" of the view to the Boolean field of the model which represents their state? I.e. the style class must update when the Boolean value changes.
(It is not required that the style class automatically updates through some kind of property binding---though, that would be OK also. It would be sufficient, if the view would be updated, for instance, by a controller instance which periodically polls the model.)
Upvotes: 2
Views: 2023
Reputation: 159341
You could use a property based CSS based psuedo-class for this.
If you want, you can bind the property which is backed by the CSS psuedo-class to a property of your model object, so when you update the model, the CSS pseudo-class of the associated view is automatically modified and the view updated as appropriate.
In the image below, each circle represents a bulb. Each bulb has an associated property which represents it's state (a BooleanProperty indicating whether the bulb is on or not). The invalidated()
method of the property is used to trigger notifications of changes to an associated CSS pseudo-class state, which updates the style of the bulb depending upon whether the bulb is switched on or not.
As onProperty()
is an exposed property of bulb, you can bind it to an appropriate boolean property of your model. This is a similar implementation in some ways to how other CSS pseudo-class backed controls in the JavaFX API work, such as check-boxes and toggle buttons.
bulb.css
.bulb {
-fx-fill: lightslategray;
}
.bulb:on {
-fx-fill: gold;
}
LightArray.java
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class LightArray extends Application {
@Override
public void start(final Stage stage) throws Exception {
Bulb bulb1 = new Bulb();
Bulb bulb2 = new Bulb();
bulb2.setOn(true);
final HBox layout = new HBox(10, bulb1, bulb2);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout);
scene.getStylesheets().add(
this.getClass().getResource("bulb.css").toExternalForm()
);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
static private class Bulb extends Circle {
Bulb() {
super(30);
getStyleClass().add("bulb");
}
public void setOn(boolean on) {
this.on.set(on);
}
public boolean isOn() {
return on.get();
}
public BooleanProperty onProperty() {
return on;
}
public BooleanProperty on =
new BooleanPropertyBase(false) {
@Override protected void invalidated() {
pseudoClassStateChanged(ON_PSEUDO_CLASS, get());
}
@Override public Object getBean() {
return Bulb.this;
}
@Override public String getName() {
return "on";
}
};
private static final PseudoClass
ON_PSEUDO_CLASS = PseudoClass.getPseudoClass("on");
}
}
Upvotes: 3