Michal Rama
Michal Rama

Reputation: 299

Change the object's properties using animation

import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class NewFXMain extends javafx.application.Application {

    @Override
    public void start(Stage primaryStage) {
        var pane = new Pane();
        var rectangle = new Rectangle(300, 100, 400, 400);
        var text = new Text(100, 100, "Java");
        rectangle.setOnMouseEntered((event) -> {
            var fill = new FillTransition(Duration.millis(1000), rectangle, (Color) rectangle.getFill(), Color.GREEN);
            var timeline = new Timeline(new KeyFrame(Duration.millis(1000), new KeyValue(text.effectProperty(), new BoxBlur(4, 4, 4))));
            var transition = new ParallelTransition(fill, timeline);
            transition.play();
        });
        pane.getChildren().addAll(rectangle, text);
        Scene scene = new Scene(pane, 1000, 720, true, SceneAntialiasing.BALANCED);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

This code should create an animation to change the color of the rectangle and blur the text.

However, while FillTransition works perfectly well, BoxBlur effect occurs without animation after 1 second.

How do I write effectProperty correctly to create an animation?

Please help.

Thank you

Upvotes: 1

Views: 499

Answers (1)

Slaw
Slaw

Reputation: 45806

None of the Effect classes, as of JavaFX 12, implement Interpolatable. This means the animation can't gradually go from no effect to an end effect, thus your animation jumps from null to BoxBlur. You should animate the properties of the BoxBlur instance, rather than the effect property itself.

Here's an example:

import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public final class App extends Application {

    @Override
    public void start(Stage primaryStage) {
        var rectangle = new Rectangle(150, 100);

        var text = new Text("Hello, World!");
        text.setFill(Color.WHITE);

        var effect = new BoxBlur(0, 0, 1);
        text.setEffect(effect);

        var animation = new ParallelTransition(
                new FillTransition(Duration.seconds(1), rectangle, Color.BLACK, Color.GREEN),
                new Timeline(
                        new KeyFrame(Duration.ZERO,
                                new KeyValue(effect.widthProperty(), 0),
                                new KeyValue(effect.heightProperty(), 0)
                        ),
                        new KeyFrame(Duration.seconds(1),
                                new KeyValue(effect.widthProperty(), 10),
                                new KeyValue(effect.heightProperty(), 10)
                        )
                )
        );
        rectangle.setOnMouseEntered(event -> {
            event.consume();
            animation.setRate(1);
            animation.play();
        });
        rectangle.setOnMouseExited(event -> {
            event.consume();
            animation.setRate(-1);
            animation.play();
        });

        primaryStage.setScene(new Scene(new StackPane(rectangle, text), 500, 300));
        primaryStage.show();
    }

}

Upvotes: 4

Related Questions