mercredi 15 juin 2016

Using a StringProperty as a parameter of a KeyValue method

I'm trying to make an animated button by gradually changing it's style using a CSS file.

I researched about it, and I got to this this question. I saw the accepted answer and I tried to implement the solution that that person gave.

What I did is basically creating a CustomButton class that extends Button, and then setting up StringProperties whose values change depending on if the button is clicked or not; then, every single StringProperty is concatenated so then they work as an alternative to a CSS file, being applied as a style to a button.

I think everything is coded fine, the problem is that I can't create the animation that should be played when the button is pressed because for that I'd need to create a Timeline whose Keyframe's KeyValues specify the value of each one of the components that conform the animation, and it turns out that StringProperties can't work as parameters for a KeyValue method.

This is the CustomButton class:

public class CustomButton extends Button{


BooleanProperty clicked = new SimpleBooleanProperty(false); // Its value changes each time the button is clicked.

StringProperty oldRotationValue = new SimpleStringProperty("-fx-rotate: -360;"); // Stores the last value of rotationStringProperty, so 
                                                                                 // then it can be used as the first frame of an animation.

StringProperty oldColorValue = new SimpleStringProperty("#E74C3C;"); // Stores the last value of colorStringProperty, so 
                                                                     // then it can be used as the first frame of an animation.

StringProperty oldSizeValue = new SimpleStringProperty("-fx-size: " + "180px;"); // Stores the last value of sizeStringProperty, so 
                                                                                 // then it can be used as the first frame of an animation.
public CustomButton(){
    Button button = createButton(rotationStringProperty, colorStringProperty, sizeStringProperty);
} //CustomButton constructor

StringProperty rotationStringProperty = new SimpleStringProperty(); // Creates the rotationStringProperty.
StringProperty colorStringProperty = new SimpleStringProperty(); // Creates the colorStringProperty.
StringProperty sizeStringProperty = new SimpleStringProperty(); // Creates the sizeStringProperty.

private void setRotationStringProperty() { // Method that sets the rotation value depending on whether the button was pressed or not.

    if (!clicked.getValue()) { // If the button wasn't clicked.
        oldRotationValue.set("-fx-rotate: " + "-360;");
        rotationStringProperty.set("-fx-rotate: " + "360;");
    } else { // If the button was clicked.
        oldRotationValue.set("-fx-rotate: " + "360;");
        rotationStringProperty.set("-fx-rotate: " + "-360;");
    }
}

private StringProperty setColorStringProperty() { // Method that sets the color depending on whether the button was pressed or not.
    if (!clicked.getValue()) { // If the button wasn't clicked.
        oldColorValue.set("#EA6153;");
        colorStringProperty.set("#E74C3C;");
    } else { // If the button was clicked.
        oldColorValue.set("#E74C3C;");
        colorStringProperty.set("#EA6153;");
    }
}

private StringProperty setSizeStringProperty() { // Method that sets the size depending on whether the button was pressed or not.
    if (!clicked.getValue()) { // If the button wasn't pressed
        oldSizeValue.set("-fx-size: " + "200px;");
        sizeStringProperty.set("-fx-size: " + "180px;");
    } else { // If the button was pressed.
        oldSizeValue.set("-fx-size: " + "180px;");
        sizeStringProperty.set("-fx-size: " + "200px;");
    }
}

private void setSizeStringMediumProperty(){ // Sets the size that the button must have in the middle of the animation.
    if(!clicked.getValue()){ // If the button wasn't pressed.
        sizeStringProperty.set("-fx-size: " + "170px;");
    }else{ // If the button was pressed.
        sizeStringProperty.set("-fx-size: " + "210px;"); 
    }
}

private Button createButton(StringProperty rotationStringProperty, //Method that creates a button and defines the its rotation, 
                                                                   // color, size, and how these has to be animated.
                                                                   // Once everything is done, it returns the customized button.
                            StringProperty colorStringProperty,
                            StringProperty sizeStringProperty) {

    Button button = new Button(); // Creates a normal JavaFX Button so then it can be modified.

    buttonSetOnAction(button); // Sets the action that the button must perform when it's clicked.

    setRotationStringProperty(); // Sets the rotationStringProperty.
    setColorStringProperty(); // Sets the colorStringProperty.
    setSizeStringProperty(); // Sets the sizeStringProperty.

    button.styleProperty().bind(new SimpleStringProperty("-fx-background-color: ") // Set's the style of the button.
                                .concat(colorStringProperty)
                                .concat(sizeStringProperty)
                                .concat(rotationStringProperty)
                                .concat("fx-border-color; #c0392b;")
                                .concat("-fx-border-width: 15px;"));
    return button; // Returns the button.
}

private void buttonSetOnAction(Button button){ // Definition of a method that sets the actions that the button must perform when it's clicked.
    button.setOnAction(e -> {
        clicked.set(!clicked.getValue()); // The value of clicked is set to its opposite.
        Timeline animation = new Timeline( //Defines an animation
                new KeyFrame(Duration.seconds(0), new KeyValue(oldRotationValue, oldColorValue, oldSizeValue));
                setSizeStringMediumProperty(); // Sets the size that the button must have at the middle of the animation.
                new KeyFrame(Duration.seconds(0.25), new KeyValue(sizeStringProperty));
                setSizeStringProperty(); // Sets the size that the button must have at the end of the animation.
                new KeyFrame(Duration.seconds(0.50), new KeyValue(rotationStringProperty, colorStringProperty, sizeStringProperty));
                );
        animation.play(); // Plays the animation;
    });
}
}

Can anyone think of an alternative to using StringProperties?

NOTE: I know that "-fx-size: " does nothing, but I don't know how to change the button's size in CSS. I'll ask that in another question once I can solve the animation problem.

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire