【问题标题】:Wrong starting and ending on TranslateTransition in JavafxJavafx 中 TranslateTransition 的开始和结束错误
【发布时间】:2016-07-12 15:45:15
【问题描述】:

我正在尝试模拟排序算法。所以我需要移动两个数字来显示它们之间的交换。但大多数时候它开始从错误的地方移动到另一个错误的地方。这是我使用 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);
                }
            }
        }
    }
}

这是控制器类:

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.

我该如何解决这些问题?

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

【问题讨论】:

  • 我尝试了你的第一个版本,添加了我能做的最少量的代码,使它成为一个可执行的例子,它工作得很好。因此,您的错误在代码的其他部分。请edit 你的问题包括一个minimal reproducible example 来证明问题(这样你就可以保证你的问题包括你做错的任何事情)。
  • 不是xy 属性,而是translateXtranslateY 属性是动画的。这会打乱您对先前移动节点的计算。
  • @James_D 第一个版本在这里大部分时间都不起作用。我试图添加更多来澄清。我已经在谷歌驱动器上上传了完整的包并且也提供了那个链接。如果我需要更具体,请告诉我。
  • @fabian 我无法得到我必须做的事情。是否可以指定要移动的新坐标?比如,这里我需要将 text1 移动到 text2 的 X 轴位置,反之亦然。

标签: animation javafx transition


【解决方案1】:

您使用Textxy 位置。然而,这不是所有Nodes 共有的属性。动画属性是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();
}

【讨论】:

  • 非常感谢先生。费边。最后,我成功实现了您给定的代码。现在它工作得很好,正如我所需要的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多