Как правильно реализовать Action Listener в анимации яблочко - PullRequest
0 голосов
/ 22 ноября 2018

Эта программа сначала отображает яблочко, созданное тремя кругами разных размеров.После нажатия кнопки animate me функция animation() заставит существующие круги сжиматься внутрь до тех пор, пока размер кружков не станет равным нулю.

Когда пользователь нажмет кнопку «Нажать, чтобы остановить», анимацияпотом остановится.Если пользователь снова нажмет кнопку, он продолжит движение из состояния, в котором он был остановлен, и т. Д.

В настоящее время это работает не так, как предполагалось.Он создает всего около 9 кругов (включая девять кругов, с которых началась программа).Я знаю, что мне нужно будет использовать обработчик действий, чтобы запустить программу, но у меня возникают трудности с документацией слушателя действий.Что я должен указать в параметрах слушателя?Если вы видите какие-либо другие способы обойти это, пожалуйста, дайте мне знать.

package target;

import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Target extends Application 
{
    Circle[] cir = new Circle[7];
    Button btn = new Button("Animate me!");
    StackPane root = new StackPane();

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

    /** 
     * start method will create the target and the start button first 
     * displayed on-screen to the user 
     */
    @Override
    public void start(Stage primaryStage) 
    {

        root.setStyle("-fx-border-color:black;");      

        cir[0] = new Circle(400, 250, 200);
        cir[0].setFill(Color.RED);
        cir[0].setStyle("-fx-border-color:black;");

        cir[1] = new Circle(315, 165, 115);
        cir[1].setFill(Color.WHITE);
        cir[1].setStyle("-fx-border-color:black;");

        cir[2] = new Circle(230, 80, 30);
        cir[2].setFill(Color.RED);
        cir[2].setStyle("-fx-border-color:black;");

        root.getChildren().addAll(cir[0], cir[1], cir[2]);      
        root.getChildren().add(btn);     

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        btn.setOnAction(e ->
        {
            animation();
            btn.setText("Press to Stop");
        });
    }

    public void animation()
    {
        //Timeline animation = new Timeline(
        //)

        ScaleTransition[] st = new ScaleTransition[7];
        boolean recycleCircles = false;

        st[0]= new ScaleTransition(Duration.seconds(7), cir[0]);
        st[0].setToX(0.0f);
        st[0].setToY(0.0f);
        st[0].play();

        st[1] = new ScaleTransition(Duration.seconds(5.5), cir[1]);
        st[1].setToX(0.0f);
        st[1].setToY(0.0f);
        st[1].play();

        st[2] = new ScaleTransition(Duration.seconds(4), cir[2]);
        st[2].setToX(0.0f);
        st[2].setToY(0.0f);
        st[2].play();

       // int delayInc = 1;
        int delay = 1;

        //will create circles (will rotate between white and red) and then add 
        //to scaleTransitions
        //while(btn.isPressed() == false)
        {     
            for(int i = 3; i<st.length; i++)
            {     
                if(recycleCircles == true)
                {
                    i = 0;
                    recycleCircles = false;
                }
                if(i % 2 == 1)
                {
                    cir[i] = new Circle(400,250,200);
                    cir[i].setFill(Color.WHITE);
                    cir[i].setStyle("-fx-border-color:black;");
                    root.getChildren().add(cir[i]);
                    cir[i].toBack();

                    st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
                    st[i].setDelay(Duration.seconds(delay));
                    delay++;
                    st[i].setToX(0.0f);
                    st[i].setToY(0.0f);
                    st[i].play();

                }
                else if(i%2==0)
                {
                    cir[i] = new Circle(400, 250, 200);
                    cir[i].setFill(Color.RED);
                    cir[i].setStyle("-fx-border-color:black;");
                    root.getChildren().add(cir[i]);
                    cir[i].toBack();

                    st[i] = new ScaleTransition(Duration.seconds(7), cir[i]);
                    st[i].setDelay(Duration.seconds(delay));
                    delay++;
                    st[i].setToX(0.0f);
                    st[i].setToY(0.0f);
                    st[i].play();
                }
                if(i == 6)
                    recycleCircles = true;
            }
        }

        //btn.pressedProperty().addListener(listener);

        btn.setOnMousePressed(event ->
        {   
        });   

        btn.setOnMouseReleased(event -> 
        {
            for(int y = 0; y<st.length;y++)
            {       
            }
        });


    }  
}

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Код, присвоенный setOnAction, представляет собой EventHandler, то есть @FunctionalInterface с единственным методом handle.Это означает, что вы можете вместо этого дать ему лямбда-выражение.Метод принимает аргумент, который представляет собой ActionEvent нажатие кнопки (созданной для вас JavaFX), и запускает код, который вы ему даете.

Если вы хотите приостановить анимацию, вызовите Animation#pause, и если вы хотите возобновить его, позвоните Animation#play.Я предлагаю вам создать ParallelTransition со всеми вашими ScaleTransition в качестве его детей.Затем вызовите перечисленные выше методы для ParallelTransition в обработчике событий.

Это означает, что код установки, например, присвоение имени кнопке и создание анимации, выходит за пределы обработчика события.

0 голосов
/ 22 ноября 2018

Не уверен, есть ли у вас какой-либо конкретный вариант использования с каждым кругом.Если вы используете круги только для чередования цветов строк, то вы можете получить аналогичный эффект с опцией повторения радиального градиента.

В той степени, в которой я понимаю вопрос, я могу думать о программе ниже.Может быть, это может вам помочь.

Просто чтобы вы знали, общий эффект немного отличается от вашей программы.Основное различие в эффектах заключается в том, что ваша программа создает эффект / впечатление, что каждый круг сужается к центру, так как расстояние между каждым кругом всегда одинаково, пока оно не сжимается полностью.Моя программа дает эффект / впечатление, как будто вся доска отходит от вашего взгляда, пока не исчезнет.В моей программе расстояние между каждым кругом уменьшается пропорционально до тех пор, пока оно не уменьшится.

import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class TargetAnimation extends Application {
    Button btn = new Button("Animate me!");
    StackPane root = new StackPane();

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

    @Override
    public void start(Stage primaryStage) {
        root.setPrefSize(400, 400);
        root.setStyle("-fx-border-color:black;");

        Circle board = new Circle();
        board.setRadius(200);
        board.setStyle("-fx-fill:radial-gradient(focus-angle 0deg , focus-distance 0% , center 50% 50% , radius 21% , repeat, red 44% , white 46% );-fx-stroke-width:1px;-fx-stroke:black;");

        root.getChildren().addAll(board, btn);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        ScaleTransition transition = new ScaleTransition(Duration.seconds(7), board);
        transition.setToX(0);
        transition.setToY(0);
        btn.setOnAction(e -> {
            switch (transition.getStatus()) {
                case RUNNING:
                    transition.pause();
                    break;
                case PAUSED:
                    transition.play();
                    break;
                default:
                    board.setScaleX(1);
                    board.setScaleY(1);
                    transition.playFromStart();
            }
        });
    }
}
...