使用 LineTo、MoveTo 将按钮移动到 JavaFX 中的指定坐标

Moving a button to specified coordinates in JavaFX with a Path Transition using LineTo, MoveTo

我正在制作一个动画,其中涉及代表网络中传输的数据的移动按钮。到目前为止,我已经能够通过更新按钮的 LayoutX 和 LayoutY 字段以及使用顺序转换将按钮移动到动画不同阶段的不同位置。

但现在我正在尝试让名为 blue 的按钮沿对角线从它在舞台上的位置移动到 "router 3,",它位于按钮的上方和右侧。目的地的确切Layout坐标为426(x)和364(y),起始位置的Layout坐标为309(x)和585(y)。我一直在尝试将 moveTo 与 LineTo 结合使用以将按钮移至上述坐标,但事实证明这很困难,原因有二:

首先,我使用了一个过渡来到达起始坐标,所以按钮到达起始位置时的实际坐标是 LayoutX: 14, LayoutY: 445,TranslateX:295,TranslateY:140。 我尝试用代码纠正这个问题:

        blue.setLayoutX(blue.getLayoutX() + blue.getTranslateX());
        blue.setLayoutY(blue.getLayoutY() + blue.getTranslateY());
        blue.setTranslateX(0);
        blue.setTranslateY(0);

然后定义蓝色要遵循的路径为:

        Path path = new Path();
        MoveTo start = new MoveTo();
        start.setX(blue.getTranslateX());
        start.setY(blue.getTranslateY());
        path.getElements().add(start);
        path.getElements().add(new LineTo(125.0f, -220.0f));
        PathTransition pathTransition = new PathTransition();
        pathTransition.setDuration(Duration.millis(1000));
        pathTransition.setPath(path);
        pathTransition.setNode(blue);
        pathTransition.setCycleCount((int) 1f);
        pathTransition.setAutoReverse(false);
        pathTransition.play();

但这似乎是一个麻烦的解决方法。例如,根据 Dijkstra 的算法,该程序的下一阶段具有遍历多个 "routers" 网络的按钮,我希望能够定义一条直接通往下一个路由器的线路路径,无需在每个阶段使用翻译和布局坐标 fiddle。或者,例如Swing可以重新绘制一个圆,同时逐像素更新其坐标,从而制作对角线动画并在到达某个位置后停止。这可能使用 JavaFX 吗?

其次,即使开始执行此动画时,按钮似乎也"jump back"轻微,好像要移动的路径的起点是将像素向下和按钮实际所在位置的左侧耦合,即使据我所知我已经将路径的起点指定为动画开始之前按钮所在的位置。这有什么特别的原因吗?

感谢您对我的问题的任何帮助;这是我第一次使用 Whosebug。我很确定我已经非常彻底地搜索了这类问题的答案,但如果这是重复的,我很抱歉。

这是一个已知问题,您可以在 Create a path transition with absolute coordinates for a StackPane object 讨论帖中阅读相关内容。

不幸的是,您必须解决该问题,JavaFX 中没有解决方案。幸运的是解决方案很简单,只需使用 MoveTo 和 LineTo 的修改版本。

这是为您修改的示例代码。只需单击场景中的某个位置,节点就会移动到那里,而无需 "jumping".

public class PathTransitionExample extends Application {

    PathTransition transition;

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

        Group root = new Group();

        // create movable object
        Rectangle rect = new Rectangle(50, 50);
        rect.setStroke(Color.BLUE);
        rect.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));
        rect.relocate(100, 80);
        root.getChildren().add(rect);

        Label label = new Label("Click on scene to set destination");
        label.relocate(0, 0);
        root.getChildren().add(label);

        // init transition
        transition = new PathTransition();
        transition.setNode(rect);
        transition.setDuration(Duration.seconds(2));

        Scene scene = new Scene(root, 1024, 768);

        scene.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<Event>() {

            @Override
            public void handle(Event event) {

                transition.stop();

                setPositionFixed( rect);

                double toX = ((MouseEvent) event).getX();
                double toY = ((MouseEvent) event).getY();

                Path path = new Path();
                path.getElements().add(new MoveToAbs(rect));
                path.getElements().add(new LineToAbs(rect, toX, toY));

                transition.setPath(path);
                transition.play();

            }

            // change layout to current position, reset translate
            private void setPositionFixed( Node node) {
                double x = rect.getLayoutX() + rect.getTranslateX();
                double y = rect.getLayoutY() + rect.getTranslateY();
                rect.relocate(x, y);
                rect.setTranslateX(0);
                rect.setTranslateY(0);
            }

        });

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

    }

    public static class MoveToAbs extends MoveTo {

        public MoveToAbs(Node node) {
            super(node.getLayoutBounds().getWidth() / 2, node.getLayoutBounds().getHeight() / 2);
        }

        public MoveToAbs(Node node, double x, double y) {
            super(x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
        }

    }

    public static class LineToAbs extends LineTo {

        public LineToAbs(Node node, double x, double y) {
            super(x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
        }

    }

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

}