JavaFX:在TextArea中显示文本,每行之间有延迟

时间:2018-04-05 12:25:07

标签: java javafx textarea delay

我正在尝试在TextArea中显示文本,并在每个句子之间延迟,就像你正在进行对话一样。 我尝试使用sleep函数但这不起作用,因为只有当所有方法都停止运行时才会显示文本。 什么是一种有效的方法:

(伪代码)

textArea.appendText("Goodday sir, how are you doing?");
(0.5 second delay);
textArea.appendText("I'm fine thanks");
(1 second delay);
textArea.appendText("What can I do for you?");
getPlayerInput();
textArea.appendText("Sure, I'll take care of it.");

澄清我正在尝试做的事情: 在textArea中显示文本,中间有延迟,并且能够在两者之间运行函数。

2 个答案:

答案 0 :(得分:1)

您可以使用时间轴onFinished在JavaFX中执行延迟操作

尝试以下代码

package application;

import java.util.ArrayList;
import java.util.Iterator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {
    Timeline delay = new Timeline();
    TextArea textArea = new TextArea();
    boolean waitForInput = false;
    Msg current;

    @Override
    public void start(Stage primaryStage) {

        StackPane root = new StackPane();

        root.getChildren().add(textArea);

        Scene scene = new Scene(root, 500, 500);

        ArrayList<Msg> msgs = new ArrayList<Msg>();
        msgs.add(new Msg("Goodday sir, how are you doing?\n", Duration.seconds(1), false));
        msgs.add(new Msg("i'm fine thanks!\n", Duration.seconds(2), false));
        msgs.add(new Msg("What can I do for you?\n", Duration.seconds(0.1), true));
        msgs.add(new Msg("Sure, I'll take care of it.\n", Duration.seconds(1), false));
        msgs.add(new Msg("....", Duration.seconds(0.5), false));
        msgs.add(new Msg("are you sure it's the only thing you need?\n", Duration.seconds(0.1), true));
        msgs.add(new Msg("alright bye", Duration.seconds(0), true));

        Iterator<Msg> it = msgs.iterator();
        delay.getKeyFrames().setAll(new KeyFrame(Duration.seconds(0)));
        delay.setOnFinished(e -> {
            if (it.hasNext()) {
                current = it.next();
                delay.getKeyFrames().setAll(new KeyFrame(current.getDuration()));
                delay.playFromStart();
                textArea.appendText(current.getContent());
                if (current.requiresInput()) {
                    waitForInput = true;
                    delay.pause();
                }
            }
        });
        delay.playFromStart();

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

        scene.addEventFilter(KeyEvent.KEY_PRESSED, e ->
        {
            if (waitForInput && e.getCode().equals(KeyCode.ENTER)) {
                delay.play();
                waitForInput = false;
            }
        });
        scene.addEventFilter(KeyEvent.KEY_TYPED, e -> {
            if (!waitForInput) {
                e.consume();
            }
        });

    }

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

    class Msg {
        private boolean requireInput;
        private String content;
        private Duration duration;

        public Msg(String c, Duration d, boolean b) {
            content = c;
            duration = d;
            requireInput = b;
        }

        public String getContent() {
            return content;
        }

        public Duration getDuration() {
            return duration;
        }

        public boolean requiresInput() {
            return requireInput;
        }
    }
}

答案 1 :(得分:1)

作为其他答案中时间轴的变体,您可以为要显示的每条消息创建不同的KeyFrame。这避免了拥有&#34;嵌套时间线&#34;的情况,如果您有两个或三个以上的消息一个接一个地显示,我认为这将变得无法管理。

这是一个使用这个想法的SSCCE:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Conversation extends Application {

    private TextArea console ;
    private TextField input ;
    private BooleanProperty readyForInput ;

    private Timeline createTimeline(String[] messages) {
        Timeline timeline = new Timeline();
        Duration delayBetweenMessages = Duration.seconds(1);
        Duration frame = delayBetweenMessages ;
        for (String msg : messages) {
            timeline.getKeyFrames().add(new KeyFrame(frame, e -> console.appendText(msg+"\n")));
            frame = frame.add(delayBetweenMessages);
        }
        timeline.statusProperty().addListener((obs, oldStatus, newStatus) -> {
            readyForInput.set(newStatus != Animation.Status.RUNNING);
            if (newStatus != Animation.Status.RUNNING) {
                input.requestFocus();
            }
        });
        return timeline ;
    }

    @Override
    public void start(Stage primaryStage) {

        readyForInput = new SimpleBooleanProperty(false);

        console = new TextArea();
        console.setEditable(false);

        input = new TextField();
        input.disableProperty().bind(readyForInput.not());

        input.setOnAction(e -> {
            String inputText = input.getText();
            console.appendText("> "+inputText+"\n");
            input.clear();
            createTimeline(getMessages(inputText)).play();
        });

        BorderPane root = new BorderPane(console, input, null, null, null) ;
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();

        createTimeline(getMessages(null)).play();
    }

    private String[] getMessages(String input) {
        if (input == null || input.isEmpty()) {
            return new String[] {
                    "Goodday sir, how are you doing?",
                    "I'm fine thanks",
                    "What can I do for you?"
            };
        } else {
            // AI logic here...
            return new String[] { "Sure, I'll take care of it." };
        }
    }

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