有没有办法在GridPane中设置元素动画

时间:2019-12-10 14:51:57

标签: java animation javafx

我正在为GridPane中的元素设置动画。我有一个Unit类,它表示我要移动的内容。

public class Unit {
    private Text text;
    private Rectangle rectangle;
    private StackPane stackPane;

    public Unit(Text text, Rectangle rectangle) {
        this.text = text;
        this.rectangle = rectangle;
        text.setFill(Color.WHITE);
        stackPane = new StackPane(rectangle, text);
    }

    public Text getText() {
        return text;
    }

    public void setText(Text text) {
        this.text = text;
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public void setRectangle(Rectangle rectangle) {
        this.rectangle = rectangle;
    }

    public StackPane getStackPane() {
        return stackPane;
    }

    public void setStackPane(StackPane stackPane) {
        this.stackPane = stackPane;
    }
}

这就是我现在移动事物的方式

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        GridPane gridPane = new GridPane();
        gridPane.setVgap(5);
        gridPane.setHgap(5);

        Unit unit = new Unit(new Text("1"), new Rectangle(50, 50));
        gridPane.add(unit.getStackPane(), 0, 0);

        TranslateTransition translateTransition = new TranslateTransition();
        translateTransition.setDuration(Duration.seconds(6));
        translateTransition.setToX(200);
        translateTransition.setToY(200);
        translateTransition.setNode(unit.getStackPane());
        translateTransition.play();

        Scene scene = new Scene(gridPane, 300, 275);
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

    }
}

是否可以将单位移动到特定的行-列位置。我认为网格窗格可能不适合我的目的,但这是按我想要的方式布局事物的简单方法。

2 个答案:

答案 0 :(得分:1)

这是一个基于Animation upon layout changes(同样要点https://gist.github.com/jewelsea/5683558)中的布局动画制作器的示例。我真的不知道这是否真的是您想要的(可能很接近)。但无论如何,它都非常整洁;-)

在这里,我不会对其进行过多解释,因为有关它是什么以及它如何工作的主要解释是在先前链接的问题上。

所引用的Unit类是您提出的问题。

AnimatedSparseGrid.java

import javafx.animation.*;
import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.Point2D;
import javafx.scene.*;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.*;

public class AnimatedSparseGrid extends Application {    
    private static final int NUM_UNITS = 10;
    private static final int UNIT_SIZE = 30;
    private static final int GRID_SIZE = 5;
    private static final int GAP = 5;
    private static final Duration PAUSE_DURATION = Duration.seconds(3);

    private Random random = new Random(42);

    private ObservableList<Unit> units = FXCollections.observableArrayList();

    private GridPane gridPane = new GridPane();

    @Override
    public void start(Stage stage) throws Exception {
        configureGrid();

        LayoutAnimator animator = new LayoutAnimator();
        animator.observe(gridPane.getChildren());

        generateUnits();
        relocateUnits();

        continuouslyAnimateGrid();

        stage.setScene(new Scene(gridPane));
        stage.setResizable(false);
        stage.show();
    }

    private void configureGrid() {
        gridPane.setVgap(GAP);
        gridPane.setHgap(GAP);
        int size = GRID_SIZE * UNIT_SIZE + GAP * (GRID_SIZE - 1);
        gridPane.setMinSize(size, size);
        gridPane.setMaxSize(size, size);
    }

    private void generateUnits() {
        for (int i = 0; i < NUM_UNITS; i++) {
            Unit unit = new Unit(
                    new Text((i + 1) + ""),
                    new Rectangle(UNIT_SIZE, UNIT_SIZE)
            );

            units.add(unit);
        }
    }

    private void relocateUnits() {
        Set<Point2D> usedLocations = new HashSet<>();

        for (Unit unit : units) {
            Node node = unit.getStackPane();

            int col;
            int row;
            do {
                col = random.nextInt(GRID_SIZE);
                row = random.nextInt(GRID_SIZE);
            } while (usedLocations.contains(new Point2D(col, row)));
            usedLocations.add(new Point2D(col, row));

            GridPane.setConstraints(unit.getStackPane(), col, row);

            if (!gridPane.getChildren().contains(node)) {
                gridPane.add(node, col, row);
            }
        }
    }

    private void continuouslyAnimateGrid() {
        Timeline timeline = new Timeline(
                new KeyFrame(Duration.ZERO, event -> relocateUnits()),
                new KeyFrame(PAUSE_DURATION)
        );
        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.play();
    }

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

答案 1 :(得分:1)

有些骇人听闻,但您可以将单位移至所需的行-列,测量新的X,Y并将其用于翻译。
以下代码演示了从0,0到20,20的动画:

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

    private Button move;
    private Pane unitPane, root;
    private GridPane gridPane;

    @Override
    public void start(Stage primaryStage) throws Exception{

        gridPane = new GridPane();
        gridPane.setVgap(5);
        gridPane.setHgap(5);

        unitPane = new Unit(new Text("1"), new Rectangle(50, 50)).getStackPane();
        gridPane.add(unitPane, 0, 0);

        move = new Button("Move");
        move.setOnAction(e->animate());
        root = new BorderPane(gridPane, null, null, move, null);

        Scene scene = new Scene(root, 300, 275);
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void animate() {

        //remove unit, make it invisible, and add it to desired location
        gridPane.getChildren().remove(unitPane);
        unitPane.setVisible(false);
        gridPane.add(unitPane, 20, 20);
        root.layout(); //apply top down layout pass
        //get x y of new location
        double x = unitPane.getLayoutX(); double y = unitPane.getLayoutY(); //measure new location

        //return to original location
        gridPane.getChildren().remove(unitPane);
        gridPane.add(unitPane, 0, 0);
        unitPane.setVisible(true);

        //apply translation to x,y of new location
        TranslateTransition translateTransition = new TranslateTransition();
        translateTransition.setDuration(Duration.seconds(3));
        translateTransition.setToX(x);
        translateTransition.setToY(y);
        translateTransition.setNode(unitPane);
        translateTransition.play();
        //when translation is finished remove from original location
        //add to desired location and set translation to 0
        translateTransition.setOnFinished(e->{
            gridPane.getChildren().remove(unitPane);
            unitPane.setTranslateX(0);unitPane.setTranslateY(0);
            gridPane.add(unitPane, 20, 20);
        });
    }

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

    }
}

class Unit {

    private Text text;
    private Rectangle rectangle;
    private StackPane stackPane;

    Unit(Text text, Rectangle rectangle) {
        this.text = text;
        this.rectangle = rectangle;
        text.setFill(Color.WHITE);
        stackPane = new StackPane(rectangle, text);
    }

    public Text getText() {
        return text;
    }

    public void setText(Text text) {
        this.text = text;
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public void setRectangle(Rectangle rectangle) {
        this.rectangle = rectangle;
    }

    public StackPane getStackPane() {
        return stackPane;
    }

    public void setStackPane(StackPane stackPane) {
        this.stackPane = stackPane;
    }
}

enter image description here