根据模型状态更改JavaFX样式类

时间:2016-03-18 21:43:04

标签: javafx

我有一个带有多个圆形的JavaFX FXML场景。每个圆圈代表一个灯泡。当灯泡具有某个JavaFX CSS类时,它会打开,例如“lightOn”,否则它会关闭。 CSS定义圆的外观,使其在具有“lightOn”类时显得闪亮,在没有类时显得暗淡。

我还有一个普通的Java对象作为模型,它包含一组布尔值。每个布尔值属于视图的单个灯泡,并指示灯是打开还是关闭。

如何将视图的各个“灯泡”的样式类连接到代表其状态的模型的布尔字段?即当布尔值改变时,样式类必须更新。

(样式类不需要通过某种属性绑定自动更新 - 但是,也可以。如果视图将被更新,例如,由控制器实例更新就足够了。定期轮询模型。)

1 个答案:

答案 0 :(得分:1)

您可以使用基于CSS based psuedo-class的属性。

如果需要,可以将CSS伪造类支持的属性绑定到模型对象的属性,因此在更新模型时,会自动修改关联视图的CSS伪类,并且视图已更新。

在下图中,每个圆圈代表一个灯泡。每个灯泡都有一个相关的属性,代表它的状态(一个BooleanProperty指示灯泡是否打开)。该属性的invalidated()方法用于触发相关CSS伪类状态更改的通知,该状态根据灯泡是否打开更新灯泡的样式。

由于onProperty()是灯泡的外露属性,您可以将其绑定到模型的适当布尔属性。这在某些方面类似于JavaFX API中其他CSS伪类支持控件的工作方式,例如复选框和切换按钮。

image

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");
    }
}