Nano Hash - криптовалюты, майнинг, программирование

JavaFX: отображать текст в TextArea с задержкой между каждой строкой

Я пытаюсь отобразить текст в TextArea с задержкой между каждым предложением, как будто вы разговариваете. Я пытался использовать функцию сна, но это не работает, поскольку текст отображается только тогда, когда все методы перестают работать. Что было бы эффективным способом сделать это:

(Псевдокод)

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 с задержками между ними и иметь возможность запускать промежуточные функции.

05.04.2018

  • Во-первых: первые 0,5 секунды тоже должны быть вводными. Запуск внутреннего аутизма - сри. 05.04.2018
  • Вы можете использовать java.util-timer, который представляет компонент timeline. Здесь вы можете найти пример этого. вы можете запускать фоновые задачи, и тогда это сработает. 05.04.2018
  • а) не блокируйте поток приложения б) getPlayerInput, вероятно, не будет работать, если вы ожидаете каких-либо действий пользователя, поскольку JavaFX основан на событиях, и вы, вероятно, блокируете поток, ответственный за обработку событий. c) взгляните на многопоточность+Platform.runLater или пакет javafx.animation. 05.04.2018

Ответы:


1

В качестве варианта временной шкалы в другом ответе вы можете создать разные KeyFrame для каждого сообщения, которое хотите отобразить. Это позволяет избежать сценария с «вложенными временными шкалами», который, я думаю, стал бы неуправляемым, если бы у вас было более двух или трех сообщений для отображения одно за другим.

Вот 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);
    }
}
05.04.2018
  • вы можете использовать setAll вместо add, чтобы каждый раз использовать разные задержки 05.04.2018
  • @JavaNoob И вы бы сделали это, перебирая массив ... как именно ??? 05.04.2018
  • Это то, что мне было нужно, Это позволяет легко быстро написать разговор. Думаю, я также могу использовать HashMap, который использует строку в качестве ключа и значение в качестве продолжительности? 05.04.2018
  • Только что понял, что HashMap не имеет определенного порядка 05.04.2018
  • @WouterA Вы, безусловно, можете использовать Map (любого типа) для сопоставления сообщений с последующей паузой. (Я не вижу, чтобы порядок вещей, хранящихся на карте, вообще имел значение.) Или любая другая логика; просто замените delayBetweenMessages любым Duration, рассчитанным или найденным из содержимого сообщения. 05.04.2018

  • 2

    вы можете использовать временную шкалу 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;
            }
        }
    }
    
    05.04.2018
  • Небольшой вариант, который может быть немного проще, состоит в том, чтобы иметь несколько ключевых кадров (скажем, в 1 секунду и 2 секунды) с обработчиками событий для ключевых кадров, которые добавляют различные строки. Тогда у вас не было бы вложенных временных шкал, когда одна временная шкала создавала другую, когда она была закончена. 05.04.2018
  • действительно ему придется создать новый кадр, удалить старый и добавить вновь созданный вместо создания новой временной шкалы! 05.04.2018
  • Зачем удалять старый? 05.04.2018
  • если он изменит продолжительность, скажем, первая составляет 2 секунды, а новая - 0,5 секунды, временная шкала займет 2 секунды, чтобы закончить, 05.04.2018
  • Спасибо, это работает хорошо, но когда я хочу добавить много строк, все становится неуклюжим. 05.04.2018
  • извините за задержку xD, теперь проверьте обновление, которое мне пришлось создать класс Msg, который сохранит строку и продолжительность сообщения, а также логическое значение, будет ли оно запрашивать ввод или нет 05.04.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..