Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make an animation with CSS in JavaFX?

I want to change the style of Node by changing its style class.

Button button = new Button();
button.getStyleClass().add("class1")   
button.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent mouseEvent) {
            button.getStyleClass().add("class2");
        }
    });

Is it possible to change the style gradually, for making something like a transition?

like image 740
Eugene Avatar asked Jul 16 '13 12:07

Eugene


People also ask

Can you use CSS in JavaFX?

This topic describes how to use cascading style sheets (CSS) with JavaFX applications. Use CSS to create a custom look for your application. Style sheets contain style definitions that control the look of user interface elements. Using CSS in JavaFX applications is similar to using CSS in HTML.

How do I link CSS to JavaFX?

In the SceneBuilder view, click on the AnchorPane that was added first. In the Properties tab, under the 'JavaFX CSS' section, click on the 'Stylesheets' option. Select the CSS file, and that's it.

What is KeyFrame JavaFX?

public final class KeyFrame extends Object. Defines target values at a specified point in time for a set of variables that are interpolated along a Timeline .


2 Answers

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

Yes.

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.

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.

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

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

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.

warninggraywarningred

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);
    }
}
like image 136
jewelsea Avatar answered Oct 18 '22 13:10

jewelsea


JavaFX2 supports transitions. So you don´t need to make your animation step by step.

Have a look at this: http://docs.oracle.com/javafx/2/animations/basics.htm#CJAJJAGI

like image 31
Franz Deschler Avatar answered Oct 18 '22 13:10

Franz Deschler