在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 
最初显示是因为这是您将它们设置为的内容,在下面的这段代码中,您设置了2
PauseTransition
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();
        }
    }