如何在靶心动画中正确实现Action Listener

时间:2018-11-21 21:36:21

标签: java animation javafx javafx-8 actionlistener

此程序首先显示由三个不同大小的圆圈创建的靶心。 单击“设置动画我”按钮后,函数animation()将使现有的圆向内缩小,直到圆的大小为零。

一旦用户按下名为“ Press to stop”的按钮,动画就会停止。如果用户再次按下该按钮,它将继续从其停止的状态继续前进,依此类推。

当前,这无法正常工作。它仅创建约9个圆圈(包括程序开始时的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 :(得分:0)

不确定每个圆是否有任何特定的用例。如果您仅将圆形用作交替行颜色的目的,那么使用“径向渐变”的“重复”选项可以获得类似的效果。

据我所知,下面的程序是我能想到的。也许这可以帮助您。

仅告诉您,总体效果与程序略有不同。效果的主要区别在于,您的程序会给出一个效果/印象,即每个圆都向中心缩小,因为每个圆之间的距离始终相同,直到完全缩小为止。 我的程序会产生效果/。印象,就像整个木板都移开了视线,直到消失一样。在我的程序中,每个圆之间的距离按比例减小直到缩小。

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();
            }
        });
    }
}

答案 1 :(得分:0)

赋予setOnAction的代码是EventHandler,它是使用单一方法@FunctionalInterface的{​​{1}}。这意味着您可以给它一个lambda表达式。该方法接受一个参数,即单击按钮(由JavaFX为您创建)的handle,然后运行您提供的代码。

如果要暂停动画,请致电Animation#pause,如果要恢复动画,请致电Animation#play。我建议您创建一个ParallelTransition,并将所有ActionEvent作为其子级。然后在事件处理程序中的ScaleTransition上调用上述方法。

这意味着设置代码(如命名按钮和创建动画)位于事件处理程序的外部