如何在靶心动画中正确实现动作监听器

问题描述 投票:1回答:2

该程序首先显示由三个不同大小的圆圈创建的靶心。单击animate me按钮后,函数animation()将使现有圆圈向内缩小,直到圆圈的大小为零。

一旦用户按下名为“按停止”的按钮,动画就会停止。如果用户再次按下按钮,它将继续从停止的状态开始,依此类推。

目前,这不符合预期。它只创建了大约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++)
            {       
            }
        });


    }  
}
java animation javafx javafx-8 actionlistener
2个回答
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();
            }
        });
    }
}

0
投票

setOnAction的代码是EventHandler,这是@FunctionalInterface用单一方法handle。这意味着你可以给它一个lambda表达式。该方法接受一个参数,即点击按钮(由JavaFX为您创建)的ActionEvent,并运行您提供的代码。

如果要暂停动画,请调用Animation#pause,如果要恢复它,请调用Animation#play。我建议你创建一个ParallelTransition,你所有的ScaleTransitions作为它的孩子。然后在事件处理程序中的ParallelTransition上调用上面的方法。

这意味着设置代码(如命名按钮并创建动画)超出事件处理程序。

© www.soinside.com 2019 - 2024. All rights reserved.