且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 JavaFX 中使用 CSS 制作动画?

更新时间:2021-10-29 22:03:05

是否可以逐渐改变风格,例如进行一些过渡?

Is it possible to change style gradually, for example make some transition?

是的.

您将需要使用 setStyle 而不是样式类,因为类将是在 css 中定义的静态事物.JavaFX css 中没有直接支持动画.您需要在Java代码中执行动画步骤来修改css样式.

You will need to use setStyle rather than style classes because classes are going to be static things defined in a css. There is no direct support in JavaFX css for animation. You need to perform the animation steps in Java code to modify the css style.

我只在您想使用 css 执行转换时才真正推荐这种方法,因为没有相应的 Java API 容易获得.

I'd only really recommend this approach when you want to use css to perform the transition because there are no corresponding Java APIs easily available.

要处理动画,您可以使用标准的 javafx 动画 时间线操作css样式属性所依赖的属性.

To handle the animation, you can use the standard javafx animation Timeline to manipulate properties which the css style property depends on.

例如,将您的样式属性绑定到字符串.然后在时间轴中改变要更改的组件(在本例中为 colorStringProperty).

For example, bind your style property to string. Then vary the component you want to change (in this case the colorStringProperty) in a timeline.

warningButton.styleProperty().bind(
    new SimpleStringProperty("-fx-base: ")
        .concat(colorStringProperty)
        .concat(";")
        .concat("-fx-font-size: 20px;")
);

这是一个示例,它使用 css 使按钮闪烁,按下时按钮的基色从灰色逐渐过渡到红色.

Here is a sample which flashes a button using css with a gradual color transition of it's base color from gray to red when pressed.

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

/** Shows how you can modify css styles dynamically using a timeline. */
public class Warning extends Application {

    private static final String BACKGROUND = "http://bobgreiner.tripod.com/1cc2ce10.jpg"; 

    @Override
    public void start(Stage stage) throws Exception{
        final ObjectProperty<Color> warningColor = new SimpleObjectProperty<>(Color.GRAY);
        final StringProperty colorStringProperty = createWarningColorStringProperty(warningColor);

        StackPane layout = new StackPane();
        layout.getChildren().addAll(
                new ImageView(new Image(BACKGROUND)),
                createWarningButton(
                        warningColor, 
                        colorStringProperty
                )
        );
        stage.setScene(new Scene(layout));
        stage.show();
    }

    private StringProperty createWarningColorStringProperty(final ObjectProperty<Color> warningColor) {
        final StringProperty colorStringProperty = new SimpleStringProperty();
        setColorStringFromColor(colorStringProperty, warningColor);
        warningColor.addListener(new ChangeListener<Color>() {
            @Override
            public void changed(ObservableValue<? extends Color> observableValue, Color oldColor, Color newColor) {
                setColorStringFromColor(colorStringProperty, warningColor);
            }
        });

        return colorStringProperty;
    }

    private Button createWarningButton(final ObjectProperty<Color> warningColor, StringProperty colorStringProperty) {
        final Button warningButton = new Button("Warning! Warning!");
        warningButton.styleProperty().bind(
                new SimpleStringProperty("-fx-base: ")
                        .concat(colorStringProperty)
                        .concat(";")
                        .concat("-fx-font-size: 20px;")
        );

        warningButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                Timeline flash = new Timeline(
                    new KeyFrame(Duration.seconds(0),    new KeyValue(warningColor, Color.GRAY, Interpolator.LINEAR)),
                    new KeyFrame(Duration.seconds(0.25), new KeyValue(warningColor, Color.GRAY, Interpolator.LINEAR)),
                    new KeyFrame(Duration.seconds(1),    new KeyValue(warningColor, Color.RED,  Interpolator.LINEAR)),
                    new KeyFrame(Duration.seconds(1.25), new KeyValue(warningColor, Color.RED,  Interpolator.LINEAR))
                );
                flash.setCycleCount(6);
                flash.setAutoReverse(true);
                flash.play();
            }
        });

        return warningButton;
    }

    private void setColorStringFromColor(StringProperty colorStringProperty, ObjectProperty<Color> color) {
        colorStringProperty.set(
                "rgba("
                        + ((int) (color.get().getRed()   * 255)) + ","
                        + ((int) (color.get().getGreen() * 255)) + ","
                        + ((int) (color.get().getBlue()  * 255)) + ","
                        + color.get().getOpacity() +
                ")"
        );
    }

    public static void main(String[] args) {
        launch(args);
    }
}