在JavaFX中更新两个文本对象,一个字段接着一个字段,只看到两个更改的最终结果
我显示了三个文本字段,我想更改第二个,在显示屏上查看结果(请等待几秒钟),然后更改第三个,在显示屏上查看结果。相反,我只在显示屏上看到这两个更改的结果(中间没有暂停) 所以一开始在JavaFX中更新两个文本对象,一个字段接着一个字段,只看到两个更改的最终结果,javafx,Javafx,我显示了三个文本字段,我想更改第二个,在显示屏上查看结果(请等待几秒钟),然后更改第三个,在显示屏上查看结果。相反,我只在显示屏上看到这两个更改的结果(中间没有暂停) 所以一开始 one two three 显示;接 one four five 我想看到的是 one four three 停顿一下,然后 one four five 如果你的我想看的是,我不确定这是否是打字错误,但如果这不是你得到的原因 one two three 最初显示是因为这是您将它们设置为的内容,在下面的这段
one
two
three
显示;接
one
four
five
我想看到的是
one
four
three
停顿一下,然后
one
four
five
如果你的
我想看的是,我不确定这是否是打字错误,但如果这不是你得到的原因
one
two
three
最初显示是因为这是您将它们设置为的内容,在下面的这段代码中,您设置了2PauseTransition
s,它们在更改文本之前都有2秒钟的等待时间
private void process()
{
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> ttwo.setText("four"));
pauseTransition.play();
pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> tthree.setText("five"));
pauseTransition.play();
}
要解决这个问题,你可以做一些事情,比如
从一开始就适当地设置您想要的内容
运行ttwo.setText(“四”)
在过程()的开始处
这样做之后,您将得到
one
four
three
暂停转换完成2秒后,您将看到
one
four
five
在pauseTransition.play()之后代码>将新值指定给暂停转换
并在第一个值完成之前很久再次播放。
更好的方法是:
引入计数器字段:private int counter=0代码>
并像这样使用它:
private void process() {
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event ->{
show(counter++);
if(counter < 5 ) pauseTransition.play();//stop criteria
});
pauseTransition.play();
}
private void show(int counter) {
//respond based on counter
}
private void进程(){
PauseTransition PauseTransition=新的PauseTransition(持续时间.秒(2));
pauseTransition.setOnFinished(事件->{
显示(计数器++);
if(计数器<5)pauseTransition.play();//停止条件
});
暂停转换。播放();
}
私人无效显示(整数计数器){
//基于计数器的响应
}
以下是演示该想法的示例(这并不是为了演示我不清楚的您想要的确切行为):
导入javafx.animation.PauseTransition;
导入javafx.application.application;
导入javafx.geometry.Insets;
导入javafx.scene.scene;
导入javafx.scene.layout.VBox;
导入javafx.scene.text.text;
导入javafx.stage.stage;
导入javafx.util.Duration;
公共类FxMain扩展了应用程序{
专用整数计数器=0;
私人最终文本音调=新文本(“一”),
ttwo=新文本(“两个”),
tthree=新文本(“三”);
@凌驾
public void start(Stage primaryStage)引发异常{
VBox根=新的VBox(10);
根。设置填充(新插图(10));
root.getChildren().addAll(音调,ttwo,tthree);
初始阶段。设置场景(新场景(根,100100));
primaryStage.sizeToScene();
primaryStage.show();
过程();
}
私有无效进程(){
PauseTransition PauseTransition=新的PauseTransition(持续时间.秒(2));
pauseTransition.setOnFinished(事件->{
显示(计数器++);
如果(计数器<3){
pauseTransition.play();//停止条件
}
});
暂停转换。播放();
}
私人无效显示(整数计数器){
开关(计数器){
案例0:
音调.setText(“两个”);
打破
案例1:
ttwo.setText(“三”);
打破
违约:
tthree.setText(“四”);
打破
}
}
公共静态void main(最终字符串[]args){
发射(args);
}
}
正如其他人所提到的,您实际上同时播放了PauseTransition
s。它们在毫秒(如果不是纳秒)内启动,如果它们实际上在同一帧内完成,我也不会感到惊讶。因此,您可以同时看到两个动画的结果
一种解决方法是使用;它将按照所述列表的顺序播放动画列表
private void process() {
SequentialTransition st = new SequentialTransition();
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> ttwo.setText("four"));
st.getChildren().add(pauseTransition);
pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> tthree.setText("five"));
st.getChildren().add(pauseTransition);
st.play();
}
另一种解决方案是使用由多个配置为以递增的次数执行的s组成的
private void process() {
new Timeline(
new KeyFrame(Duration.seconds(2), event -> ttwo.setText("four")),
new KeyFrame(Duration.seconds(4), event -> tthree.setText("five"))
).play();
}
您的真正目标可能比设置某些text
对象的文本属性更复杂。您可以将任一解决方案调整为更通用的机制。下面是一个时间线的示例,它将执行任意数量的操作,每个操作之间有固定的延迟(包括最后一个操作之后):
好的,谢谢你。我真正想要的是一种更新显示的方法(这可能比我给出的示例更复杂),然后在进行下一次更新(也可能是显示的其他部分)之前暂停。我现在意识到,通过改变暂停转换中的时间延迟,我可以建立一个变化的时间表,只播放一次。但那不是我真正想要的。。。如果我的问题不清楚,很抱歉。我已经尝试了线程和平台->runLater,但在所有更改完成后,我仍然跳转到最终显示,更改之间没有停顿。我追求的是原创展示;暂停;改变暂停;改变暂停/完成。使用javafx动画工具(如PauseTransition
)时,不需要“平台->运行后期”来修改gui。使用我发布的代码并根据您的需要进行修改。Slaw,这看起来很棒,我一定会尝试一下。但是如果我用你的方法做一系列的动作会发生什么;然后转到另一个生成另一组操作的对象。在开始第二组操作之前,我如何确保第一组操作已完成(即已显示)?编辑了我的答案。斯拉夫,这看起来确实像我所追求的。非常感谢!见:
private void process() {
SequentialTransition st = new SequentialTransition();
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> ttwo.setText("four"));
st.getChildren().add(pauseTransition);
pauseTransition = new PauseTransition(Duration.seconds(2));
pauseTransition.setOnFinished(event -> tthree.setText("five"));
st.getChildren().add(pauseTransition);
st.play();
}
private void process() {
new Timeline(
new KeyFrame(Duration.seconds(2), event -> ttwo.setText("four")),
new KeyFrame(Duration.seconds(4), event -> tthree.setText("five"))
).play();
}
private static Timeline createTimeline(Duration period, Runnable... actions) {
var frames = new ArrayList<KeyFrame>(actions.length + 1);
var time = Duration.ZERO;
for (var action : actions) {
frames.add(new KeyFrame(time, event -> action.run()));
time = time.add(period);
}
frames.add(new KeyFrame(time)); // adds a delay after last action
return new Timeline(frames.toArray(KeyFrame[]::new));
}
private final Queue<Animation> animationQueue = ...;
private Animation currentAnimation;
private void playAnimation(Animation animation) {
if (animation.getCycleCount() == Animation.INDEFINITE) {
throw new IllegalArgumentException();
}
animation.setOnFinished(event -> {
currentAnimation = animationQueue.poll();
if (currentAnimation != null) {
currentAnimation.playFromStart();
}
});
if (currentAnimation != null) {
animationQueue.add(animation);
} else {
currentAnimation = animation;
animation.playFromStart();
}
}