Javafx 中 TranslateTransition 的开始和结束错误

Wrong starting and ending on TranslateTransition in Javafx

我正在尝试模拟排序算法。所以我需要移动两个数字来显示它们之间的交换。但大多数时候它开始从错误的地方移动到另一个错误的地方。这是我使用 TranslateTransition 的代码:

public static void showSwap(Text t1, Text t2)
{
    double x1, x2, z;
    x1=t1.getX();
    x2=t2.getX();
    z=x2-x1;

    pt = new PauseTransition(Duration.millis(1000));

    t1up = new TranslateTransition(Duration.millis(900), t1);
    t1up.setFromY(0);
    t1up.setToY(-55);
    t1up.setCycleCount(1);

    t1right = new TranslateTransition(Duration.millis(900), t1);
    t1right.setFromX(0);
    t1right.setToX(z);
    t1right.setCycleCount(1);

    t1down = new TranslateTransition(Duration.millis(900), t1);
    t1down.setFromY(-55);
    t1down.setToY(0);
    t1down.setCycleCount(1);
    t1.toFront();
    sequentialTransition1.getChildren().addAll(t1up,t1right,t1down,pt);

    t2down = new TranslateTransition(Duration.millis(900), t2);
    t2down.setFromY(0);
    t2down.setToY(55);
    t2down.setCycleCount(1);

    t2left = new TranslateTransition(Duration.millis(900), t2);
    t2left.setFromX(0);
    t2left.setToX(-z);
    t2left.setCycleCount(1);

    t2up = new TranslateTransition(Duration.millis(900), t2);
    t2up.setFromY(55);
    t2up.setToY(0);
    t2up.setCycleCount(1);
    t2.toFront();
    sequentialTransition2.getChildren().addAll(t2down,t2left,t2up,pt);
}

我也试过这部分,但是它得到了 NullPointerException。

public static void showSwap2(Text t1, Text t2)
{
    double x1, x2, y;
    x1=t1.getX();
    x2=t2.getX();
    y=t1.getY();

    MoveTo start1 = new MoveTo( x1, y );

    ArcTo end1 = new ArcTo();
    end1.setX(x2);
    end1.setY(y);
    end1.setRadiusX(100);
    end1.setRadiusY(100);

    Path path1 = new Path();
    path1.getElements().addAll(start1, end1);

    PathTransition transition1 = new PathTransition();
    transition1.setDuration(Duration.millis(900));
    transition1.setPath(path1);
    sequentialTransition1.getChildren().addAll(transition1);

    MoveTo start2 = new MoveTo( x1, y );

    ArcTo end2 = new ArcTo();
    end2.setX(x2);
    end2.setY(y);
    end2.setRadiusX(100);
    end2.setRadiusY(100);

    Path path2 = new Path();
    path2.getElements().addAll( start2, end2 );

    PathTransition transition2 = new PathTransition();
    transition2.setDuration(Duration.millis(900));
    transition2.setPath(path2);
    sequentialTransition2.getChildren().addAll(transition2);

}

这是我调用 showSwap() 方法的部分:

public final class BubbleSort extends SimulatorController implements Initializable
{
    public BubbleSort(Pane root,int totalNumbers)
    {
        int i, j, temp;

        for (i = totalNumbers - 2; i >= 0; i--)
        {
            for (j = 0; j <= i; j++)
            {
                Simulator.showCompare(rect.get(j), rect.get(j+1));
                if (numbers.get(j) > numbers.get(j + 1))
                {
                    Simulator.showSwap(textNumbers.get(j),textNumbers.get(j+1));
                    temp = numbers.get(j);
                    numbers.set(j,numbers.get(j+1));
                    numbers.set(j+1,temp);
                }
            }
        }
    }
}

这是控制器class:

public class SimulatorController  implements Initializable
{
    @FXML protected Canvas img ;
    @FXML protected Button prev;
    @FXML protected Button next;
    @FXML protected BorderPane root;

    protected static SequentialTransition sequentialTransition1;
    protected static SequentialTransition sequentialTransition2;
    protected int totalNumbers=5;
    protected static boolean nextMove=false;
    protected static boolean prevMove=false;
    protected static boolean simulateAutomatically=false;
    protected static ArrayList<Rectangle> rect = new ArrayList<Rectangle>();
    protected static ArrayList<Text> textNumbers=new ArrayList<Text>();
    protected ArrayList<Text> textIndex=new ArrayList<Text>();
    protected static ArrayList<Integer> numbers=new ArrayList<Integer>();
    protected ArrayList<Integer> index=new ArrayList<Integer>();
    protected static TranslateTransition t1right;
    protected static TranslateTransition t1up;
    protected static TranslateTransition t1down;
    protected static TranslateTransition t2left;
    protected static TranslateTransition t2down;
    protected static TranslateTransition t2up;
    protected static PauseTransition pt;


    @Override
    public void initialize(URL location, ResourceBundle resources) 
    {
        drawArrayAndNumbers();

        sequentialTransition1 = new SequentialTransition();         sequentialTransition2 = new SequentialTransition();         sequentialTransition1.setCycleCount(1);         sequentialTransition2.setCycleCount(1);

        new BubbleSort(root,totalNumbers);

        sequentialTransition1.play();        
        sequentialTransition2.play();


      root.setOnMouseClicked(new EventHandler<MouseEvent>()
      {
            @Override public void handle(MouseEvent mouseEvent)
            {
                  System.out.println(("X="+mouseEvent.getScreenX()+" || Y="+mouseEvent.getScreenY()));
            }
          });
    }

    void drawArrayAndNumbers()
    {
        int i, x=50, y=250, rectSizeX=70, rectsizeY=50;
        for(i=0;i<totalNumbers;i++,x+=rectSizeX+35)
        {
            rect.add(i, new Rectangle(x, y, rectSizeX, rectsizeY));
            rect.get(i).setArcHeight(10);
            rect.get(i).setArcWidth(10);
            rect.get(i).setFill(Color.SKYBLUE);

            numbers.add(i,100+(int)(Math.random()*899));
            index.add(i);

            textNumbers.add(i, new Text (x+15, y+30, Integer.toString(numbers.get(i))));
            textNumbers.get(i).setFill(Color.BLACK);
            textNumbers.get(i).setFont(new Font(25));

            textIndex.add(i, new Text (x+30, y+rectsizeY+15, Integer.toString(i)));
            textIndex.get(i).setFill(Color.BLACK);
            textIndex.get(i).setFont(new Font(15));

            root.getChildren().addAll(rect.get(i),textNumbers.get(i),textIndex.get(i));
        }

    }
}

这是完成 TranslateTrasitions 后的屏幕截图。我需要将数字保留在框中。但是他们没有移动到正确的位置。

Here, before starting the animation, the texts within the rectangle were 944 701 666 503 531. After completing the animation, the rectangles should contain the numbers 503 531 666 701 944. But it was showing those.

如何解决这些问题?

这里是完整包的下载link:https://drive.google.com/folderview?id=0B7pxly3GctSNQ1FaajY4LTFOQnM&usp=sharing

您使用了 Textxy 位置。然而,这是 属性 并非所有 Node 都通用的。动画属性是 translateXtranslateY 属性。因此

x1=t1.getX();
x2=t2.getX();
z=x2-x1;

导致 z 是原点 x 坐标之间的差异,而不是上一次转换后位置之间的差异。此外,你在动画完成之前调用它,所以即使你解决了前面提到的问题,你也使用当前位置进行计算,而不是上一个动画之后 Nodes 的位置。

要解决此问题,请保存初始位置并使用 translate 属性来定位节点:

public class SwapAnimationQueue<T extends Node> {

    private final SequentialTransition transitionUpper;
    private final SequentialTransition transitionLower;
    private final T[] nodes;
    private final double[] positionX;

    public SwapAnimationQueue(T... nodes) {
        this.transitionLower = new SequentialTransition();
        this.transitionUpper = new SequentialTransition();

        this.nodes = nodes.clone();
        positionX = new double[nodes.length];
        for (int i = 0; i < nodes.length; i++) {
            positionX[i] = nodes[i].getTranslateX();
        }
    }

    public void play() {
        this.transitionLower.play();
        this.transitionUpper.play();
    }

    public void swap(int index1, int index2) {
        if (index1 == index2) {
            return;
        }
        T temp;
        createTransition(transitionUpper, index1, index2, temp = nodes[index1], true);
        createTransition(transitionLower, index2, index1, nodes[index2], false);
        nodes[index1] = nodes[index2];
        nodes[index2] = temp;
    }

    private void createTransition(SequentialTransition transition, int startPosition, int endPosition, Node node, boolean upper) {
        double dy = upper ? -55 : 55;
        TranslateTransition vertical1 = new TranslateTransition(Duration.millis(900), node);
        vertical1.setByY(dy);

        TranslateTransition horizontal = new TranslateTransition(Duration.millis(900), node);
        horizontal.setByX(positionX[endPosition] - positionX[startPosition]);

        TranslateTransition vertical2 = new TranslateTransition(Duration.millis(900), node);
        vertical2.setByY(-dy);

        transition.getChildren().addAll(vertical1, horizontal, vertical2);
    }

}

或者圆形过渡:

private void createTransition(SequentialTransition transition, int startPosition, int endPosition, Node node, boolean upper) {
    double x1 = positionX[startPosition];
    double x2 = positionX[endPosition];
    MoveTo move = new MoveTo(x1, node.getTranslateY());

    double radius = Math.abs(x2-x1) / 2;

    ArcTo arc = new ArcTo(radius, 20, 0, x2-x1, 0, upper, true);
    arc.setAbsolute(false);

    transition.getChildren().add(new PathTransition(Duration.millis(900), new Path(move, arc), node));
}

用法

public void start(Stage primaryStage) {
    String[] text = {"3", "2", "1"};

    Text[] textNodes = new Text[text.length];

    for (int i = 0; i < text.length; i++) {
        Text t = new Text(text[i]);
        t.setTranslateX(20 + i * 50);
        t.setTranslateY(100);
        textNodes[i] = t;
    }

    SwapAnimationQueue swapper = new SwapAnimationQueue(textNodes);
    Pane p = new Pane();

    p.getChildren().addAll(textNodes);

    swapper.swap(0, 1);
    swapper.swap(1, 2);
    swapper.swap(0, 1);

    Scene scene = new Scene(p, 500, 500);

    primaryStage.setScene(scene);
    primaryStage.show();

    swapper.play();
}