Использование Thread.sleep () в приложении JavaFx - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь сделать приложение, которое показывает кнопку. Когда я нажимаю кнопку, сцена должна показывать некоторый текст (добавить метку) в течение нескольких секунд, а затем текст должен исчезнуть (удаление метки со сцены). Но на самом деле, когда я нажимаю кнопку, ничего не происходит.

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        StackPane pane = new StackPane();
        Button btn = new Button();
        Label lb = new Label("Start");
        pane.getChildren().addAll(btn);
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(pane, 300, 275));
        primaryStage.show();
        btn.setOnAction(e->{
             pane.getChildren().addAll(lb);
            try {
                Thread.sleep(300);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
           pane.getChildren().removeAll(lb);
        });
    }
    public static void main(String[] args) {
        launch(args);
    }
}

1 Ответ

4 голосов
/ 03 апреля 2020

Используйте PauseTransition:

btn.setOnAction(e->{
    pane.getChildren().addAll(lb);
    PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
    pause.setOnFinished(e -> pane.getChildren().removeAll(lb));
    pause.play();
});

Причина, по которой ваш подход не работает, заключается в том, что JavaFX эффективно использует один поток для рендеринга и обработки пользовательских событий. Он будет обновлять экран с фиксированным интервалом (60 раз в секунду в текущей реализации), но по причинам синхронизации необходимо дождаться любых ожидающих событий, которые в данный момент обрабатываются, чтобы завершить сначала. Таким образом, исходный код добавляет метку, делает паузу на 0,3 секунды, а затем удаляет метку. Поток приложения FX занят для всего этого процесса, поэтому среда FX никогда не имеет возможности перерисовать сцену, пока она происходит.

Суть в том, что вы никогда не должны блокировать поток приложения FX, вызов sleep() или выполнение длительных операций.

Обновление в ответ на дополнительный вопрос в комментарии:

Чтобы отключить всю обработку событий, вы можете вызвать setDisable(true) на root узел сцены. Поэтому, чтобы предотвратить обработку событий во время отображения метки:

btn.setOnAction(e->{
    pane.getChildren().addAll(lb);
    pane.setDisable(true);
    PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
    pause.setOnFinished(e -> {
        pane.getChildren().removeAll(lb));
        pane.setDisable(false);
    });
    pause.play();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...