gpt4 book ai didi

java - JavaFx。如何恢复?

转载 作者:行者123 更新时间:2023-12-01 22:18:23 26 4
gpt4 key购买 nike

我正在为文本编写时间表:

用法:

Text text = new Text();
......
group.getChildren().addAll(text);
root.getChildren().addAll(group);

tl.play();


这很好。如果我想暂停并继续动画,则 tl.pause();tl.play();可以做到。

现在,我想让动画从头开始,并使用 tl.stop();tl.playFromStart();,但是此组合的效果与 tl.pause();tl.play();的效果相同。

我的问题是,为什么tl.playFromStart();无法正常工作,如何恢复动画?

最佳答案

Timeline的工作方式

Timeline表示执行动画的时间段。 TimelineKeyFrames的集合组成。每个KeyFrame


必须在Timeline(您传入的Duration对象)上指定一个时间点
还可以选择指定KeyValues的集合,其中
包含WritableValue(例如,Property)和目标
那个时间点的这些WritableValue的值
可以选择指定要执行的动作,形式为
EventHandler<ActionEvent>


Timeline具有currentTime属性,该属性(当然)在播放Timeline时会随着时间的流逝而向前发展。 pause()将停止currentTime的进行,将其固定为当前值。 stop()将停止currentTime的进行,并将currentTime设置回零。

如果Timeline具有指定KeyFrameKeyValue,则随着currentTime的变化,WritableValue中指定的KeyValue将被设置为取决于currentTime的值。 (特别是,如果WritableValue是可插值的,则将在两个相邻的KeyFrames指定该KeyValueWritableValue的值之间插值。否则,该值将被设置为“最新”的KeyFrame为该WritableValue指定一个值。)

如果Timeline具有指定动作(KeyFrame s)的EventHandler<ActionEvent>,则随着currentTime超过该KeyFrame指定的时间,该动作将被调用。

为什么您的代码不适用于stop()playFromStart()

在您的情况下,您的KeyFrame指定一个操作,该操作会将新的变换添加到节点的变换列表中。请注意,这完全不依赖于currentTime,只是每次currentTime到达0.04 seconds时,都会添加一个新的转换(此外,您未显示其实现的方法shiftAndScale也会执行此操作)。因此,如果您stop()时间轴,则currentTime会重置为零,但是由于这个原因,该节点不会发生任何事情。 (实际上,currentTime仅在00.04秒之间变化。)

您的代码的其他问题

您的代码有问题,因为您有内存泄漏。 Node保持ObservableListTransform。您正在添加到此列表(经常),但从不删除任何内容。 Node非常聪明:它保留了一个隐藏的矩阵,该矩阵是所有变换的净效果;当您添加新的转换时,它将存储在列表中,然后使用简单的矩阵乘法更新“ net”矩阵。因此,您在这里不会看到任何计算性能问题:从该角度来看,它可以很好地扩展。但是,它确实存储了所有单独的转换(例如,因为它支持稍后删除它们),因此,如果让此转换运行足够长的时间,最终将耗尽内存。

您的代码的另一个(也许是次要的)问题是,当您组合所有这些转换时,您正在执行很多浮点运算。任何舍入错误最终都会累积。您应该尝试找到一种避免舍入误差累积的技术。

修改代码的方法

要解决此问题,您有两种选择:

如果动画是“自然循环的”(意味着动画在一定的固定时间(如旋转)后返回其初始状态),则只需根据该自然持续时间定义Timeline。仅以旋转为例,您可以执行以下操作:

double secondsPerCompleteCycle = (360.0 / 0.75) * 0.04 ;
Rotate rotation = new Rotate(0, new Point3D(1, 0, 0));
group.getTransforms().add(rotation);
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(secondsPerCompleteCycle),
new KeyValue(rotation.angleProperty(), 360, Interpolator.LINEAR)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();


现在 timeline.stop()currentTime设置为零,这将具有将旋转角度设置回其初始值(也为零)的效果。

如果动画不是自然重复的,我将使用(整数类型)计数器以您选择的任何时间单位跟踪“当前帧”,然后将变换的值绑定到计数器。使用相同的示例,您可以

double degreesPerFrame = 0.75 ;
LongProperty frameCount = new SimpleLongProperty();
Rotate rotation = new Rotate(0, new Point3D(1, 0, 0));
group.getTransforms().add(rotation);
rotation.angleProperty().bind(frameCount.multiply(degreesPerFrame));

Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0.04), e ->
frameCount.set(frameCount.get() + 1)));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();

// to reset to the beginning:
timeline.stop();
frameCount.set(0L);


您还可以考虑使用 AnimationTimer,具体取决于您的确切要求。不过,我会首先尝试其中一种技术。

在您的情况下,代数变得非常复杂(无论如何对我来说都是非常复杂的)。每个动作将三个变换添加到该节点。平移,比例尺和绕x轴的旋转。这些的4x4矩阵表示为:

1 0 0 tx
0 1 0 ty
0 0 1 0
0 0 0 1


对于翻译,

sx  0 0 0 
0 sy 0 0
0 0 1 0
0 0 0 1


对于规模,以及

1      0       0 0
0 cos(t) -sin(t) 0
0 sin(t) cos(t) 0
0 0 0 1


旋转。

虽然计算这三个的净效应并不太难(只需将它们相乘),但计算任意次数应用这些净矩阵就超出了我的范围(也许...)。此外,您在x方向上平移的量正在变化,这几乎是不可能的。

因此,解决此问题的另一种方法是定义单个转换并将其应用于节点,然后在每个事件上对其进行修改。这看起来像

Affine transform = new Affine() ; // creates identity transform
node.getTransforms().add(transform);

Timeline timeline = new Timeline(Duration.seconds(0.04), event -> {
double shiftX = ... ;
double shiftY = ... ;
double scaleX = ... ;
double scaleY = ... ;
double angle = 0.75 ;
Affine change = new Affine();
change.append(new Translate(shiftX, shiftY));
change.append(new Scale(scaleX, scaleY));
change.append(new Rotate(angle, new Point3D(1, 0, 0)));
transform.append(change);
});

timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();


如上所述, stop()pause()将具有(几乎)相同的效果。 (唯一的区别是再次播放时进行第一次新更新的时间,对于 stop()为0.04秒,对于 pause()则更少-在暂停下一次更新之前将保留任何时间。) “重置”动画,您只需

timeline.stop();
transform.setToIdentity(); // resets to beginning


请注意,通过使用此技术,该节点仅对其应用了一次转换。我们只是随着进展而更新该转换。四舍五入的误差仍然会累积,但是至少代数是可行的:)。

关于java - JavaFx。如何恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30489405/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com