【问题标题】:JavaFX Transition animation waitingJavaFX 过渡动画等待
【发布时间】:2015-01-22 16:08:38
【问题描述】:

这么快,我正在做一个演示用于计算机绘图的方法的程序。我需要创建时间线或动作历史记录(例如 placeVertex(x,y)、moveVertex(newX,newY) 等)并迭代(向前和向后、自动或手动)

我已经通过使用命令设计模式实现了这一点,但是这些命令中很少有使用转换。第一个想法是在每个命令之间在setOnFinished 中使用Condition 接口的lock、await 和signal,但这会导致gui 冻结。

我尝试了 SequentialTransition 但这对我的问题没有用 - 无法在转换之间动态更改属性。

是否有可能以某种方式通知生成一个过渡结束并且下一个过渡可以在没有 GUI 冻结和绘制的情况下运行?

谢谢!

编辑:我会尽量简化 这是我的命令界面和以下命令之一:

 public interface Command {
        public void execute();
  }

 public class MoveVertex implements Command {
        public MoveVertex(Data d, Vertex v, double changedX, double changedY){..};

        @Override
        public void execute() {         
            Path path = new Path();         
            path.getElements().add(new MoveTo(v.getCenterX(), v.getCenterY()));
            path.getElements().add(new LineTo(changedX, changedY));

            PathTransition pathTransition = new PathTransition();   
            pathTransition.setDuration(Duration.millis(velocity)); 
            pathTransition.setPath(path);   
            pathTransition.setNode(v.getVertex());

            pathTransition.play();  }
  }

这些命令存储在我的历史类中,基本上是

private List<Command> history;

我确实浏览了列表并执行了命令

public boolean executeNext() {
    if (history.size() != position) {
        history.get(position).execute();
        position++;
        return true;
    }
    return false;
}

并且我试图在下一个命令启动时达到状态,只有在上一个完成的情况下。尝试在两者之间放置等待/信号但没有成功。

【问题讨论】:

  • Transition's onFinsihedProperty() 不是为你工作的吗?
  • @ItachiUchiha 不是真的,例如我有一个圆圈,两个路径转换,第一个将圆圈从 0 0 移动到 100 100,第二个将相同的圆圈移动到其他地方,我确实想根据情况更新位置第一步,但即使我将新的MoveTo 位置放入onFinishedProperty() 它也不起作用,可能是因为之前已经创建了转换?
  • onFinished 对你不起作用有点奇怪,你能在你的问题中包含一个mcve 来复制这个问题吗?使用对相关事件进行操作回调的事件处理程序/属性侦听器是正确的解决方案,使用暂停或休眠 JavaFX 应用程序线程的东西是错误的解决方案。
  • @jewelsea 你好,添加了几行代码。希望对你有帮助

标签: animation javafx transition command-pattern graph-drawing


【解决方案1】:

下面的解决方案使用 Itachi 的建议,即在我们到达下一个位置后,提供一个 onFinished 处理程序以将节点移动到一个新的(随机)位置。

通过重用单个转换而不是在事件处理程序中使用递归,它可能会变得更高效(并且更易于理解)。可能没有必要为每个动作创建一个新的转换 - 但是,只要没有数十万个动作迭代,它应该是可以接受的。

import javafx.animation.*;
import javafx.application.Application;
import javafx.event.*;
import javafx.geometry.Point2D;
import javafx.scene.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.Random;

// animates moving a node forever in a random walk pattern.
public class RandomWalk extends Application {

    private static final Random random = new Random(42);

    private static final double W = 200;
    private static final double H = 200;
    private static final double R = 10;

    private static final Node node = new Circle(
            R, Color.FORESTGREEN
    );

    @Override
    public void start(Stage stage) {
        // start from the center of the screen.
        node.relocate(W / 2 - R, H / 2 - R);

        stage.setScene(new Scene(new Pane(node), W, H));
        stage.show();

        walk();
    }

    // start walking from the current position to random points in sequence.
    private void walk() {
        final Point2D to = getRandomPoint();
        final Transition transition = createMovementTransition(
                node,
                to
        );

        transition.setOnFinished(
                walkFrom(to)
        );
        transition.play();
    }

    private EventHandler<ActionEvent> walkFrom(final Point2D from) {
        return event -> {
            // Finished handler might be called a frame before transition complete,
            // leading to glitches if we relocate in the handler.
            // The transition works by manipulating translation values,
            // so zero the translation out before relocating the node.
            node.setTranslateX(0);
            node.setTranslateY(0);

            // After the transition is complete, move the node to the new location.
            // Relocation co-ordinates are adjusted by the circle's radius.
            // For a standard node, the R adjustment would be unnecessary 
            // as most nodes are located at the top left corner of the node 
            // rather than at the center like a circle is.
            node.relocate(
                    from.getX() - R,
                    from.getY() - R
            );

            // Generate the next random point and play a transition to walk to it.
            // I'd rather not use recursion here as if you recurse long enough,
            // then you will end up with a stack overflow, but I'm not quite sure
            // how to do this without recursion.
            final Point2D next = getRandomPoint();
            final Transition transition = createMovementTransition(node, next);
            transition.setOnFinished(walkFrom(next));
            transition.play();
        };
    }

    // We use a PathTransition to move from the current position to the next.
    // For the simple straight-line movement we are doing,
    // a straight TranslateTransition would have been fine.
    // A PathTransition is just used to demonstrate that this
    // can work for the generic path case, not just straight line movement.
    private Transition createMovementTransition(Node node, Point2D to) {
        Path path = new Path(
                new MoveTo(
                        0,
                        0
                ),
                new LineTo(
                        to.getX() - node.getLayoutX(),
                        to.getY() - node.getLayoutY()
                )
        );

        return new PathTransition(
                Duration.seconds(2),
                path,
                node
        );
    }

    // @return a random location within a bounding rectangle (0, 0, W, H)
    // with a margin of R kept between the point and the bounding rectangle edge.
    private Point2D getRandomPoint() {
        return new Point2D(
                random.nextInt((int) (W - 2*R)) + R,
                random.nextInt((int) (H - 2*R)) + R
        );
    }

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

【讨论】:

  • 感谢您的解决方案,不幸的是我不得不离开城镇两天,所以我会稍后再试!我会尽快做,然后让你知道它是如何工作的。我也在考虑递归,所以我很好奇。我看到的唯一问题是在生成中间暂停,然后找到它结束的点(有时可能在长递归中的某个地方)所以..我们会看到
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
  • 1970-01-01
  • 2016-02-26
  • 2016-11-01
相关资源
最近更新 更多