15

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?

SpaceCore186
  • 586
  • 1
  • 8
  • 22
Eugene
  • 1,037
  • 4
  • 20
  • 34
  • besides your question: Why dont you make use of the fancy Lambda annotation in your samplecode? Instead of the (new Eventhan...) you simply write: mouseEvent -> button.getStyleClass().add("class2"). Fancy? – Sauer Jul 28 '15 at 16:33

4 Answers4

21

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.

warninggray warningred

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);
    }
}
jewelsea
  • 150,031
  • 14
  • 366
  • 406
5

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

Franz Deschler
  • 2,456
  • 5
  • 25
  • 39
  • 7
    he asked about **CSS** animations and not programmatic animations – specializt Nov 02 '16 at 17:36
  • 1
    I know. Jewelsea mentioned, that JavaFX doesn´t support CSS animations and one would need to perform the single animation steps. I just wanted to clarify that this is not necessary if you use transitions. – Franz Deschler Nov 03 '16 at 15:07
0

I opened an issue to add such feature. So, when this issue is resolved, then JavaFX can support animation with pure CSS.

Pavel_K
  • 10,748
  • 13
  • 73
  • 186
0

CSS Transitions seem to be a work in progress; you can follow it at openjdk/jfx#870.

Example shown in the pull request:

.button {
    -fx-background-color: dodgerblue;
}

.button:hover {
    -fx-background-color: red;
    -fx-scale-x: 1.1;
    -fx-scale-y: 1.1;

    transition: -fx-background-color 0.5s ease,
                -fx-scale-x 0.5s ease,
                -fx-scale-y 0.5s ease;
}
airsquared
  • 571
  • 1
  • 8
  • 25