JavaFX и многопоточность

126
26 июля 2019, 02:10

Задача - при нажатии на определенную кнопку программы (JavaFX GUI) запустить гифку ожидания, которая будет крутиться, пока вполняется основной код. Для этого есть отдельный метод - showGif(), и его вызов через Platform.runLater отдельным потоком (запускается при нажатии на кнопку).

Проблема в том, что гифка по-прежнему запускается только после того, как весь код программы уже выполнен - т.е. не отдельным потоком в начале работы программы, как я хотел.

В похожих вопросах у людей все работает через Platform.runLater - что я делаю не так?

Действие кнопки:

   btn_find.setOnAction(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent event) {
            // отправляет введенную пользователем ссылку в обработку, показывает гифку ожидания
            new Thread(new Runnable() {
                public void run() {
                    Platform.runLater(new Runnable() {
                        public void run() {
                            showGif();
                        }
                    });
                }
            }).start();

Метод showGif():

private void showGif() {
    System.out.println("запускаю гифку");
    File file = new File("/Users/user/Desktop/cat-preloader.gif");
    String localUrl = null;
    try {
        localUrl = file.toURI().toURL().toString();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
    Image image = new Image(localUrl, 200,200, false, true);
    ImageView imageView = new ImageView(image);
    hb = new HBox();
    hb.setStyle("-fx-background-color: lightgrey");
    hb.setOpacity(0.7);
    hb.getChildren().add(imageView);
    HBox.setMargin(imageView, new Insets(300, 100, 60, 200));
    BorderPane.setMargin(hb, new Insets(0, 0,600, 0));
    MainView.pane.setCenter(hb); // здесь заминка - гиф отображается только после выполнения всей программы
    System.out.println("гифка запущена");
}
Answer 1

Запускайте нужный Вам код в бэкграунде что бы не занимать главный поток.

Это можно сделать при помощи Task:

Task<Void> task = new Task<Void>() {
        @Override protected Integer call() throws Exception {
        System.out.println("запускаю гифку");
        File file = new File("/Users/user/Desktop/cat-preloader.gif");
        String localUrl = null;
        try {
            localUrl = file.toURI().toURL().toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        Image image = new Image(localUrl, 200,200, false, true);
        ImageView imageView = new ImageView(image);
        hb = new HBox();
        hb.setStyle("-fx-background-color: lightgrey");
        hb.setOpacity(0.7);
        hb.getChildren().add(imageView);
        HBox.setMargin(imageView, new Insets(300, 100, 60, 200));
        BorderPane.setMargin(hb, new Insets(0, 0,600, 0));
        MainView.pane.setCenter(hb);
        System.out.println("гифка запущена");
        return null;
    }
};

Ну и сам запуск:

new Thread(task).start()

так же можно запускать долгие операции в таких же Тасках.

  • Platform.runLater: Если вам нужно обновить компонент GUI из потока, отличного от GUI, вы можете использовать это, чтобы поместить свое обновление в очередь, и оно будет обрабатываться потоком GUI как можно скорее.
  • Task реализует интерфейс Worker, который используется, когда вам нужно запустить длинную задачу за пределами потока графического интерфейса (во избежание замораживания вашего приложения), но все же необходимо взаимодействовать с графическим интерфейсом на определенном этапе.

Источник

READ ALSO
Упростить дерево стилей css

Упростить дерево стилей css

Как можно упростить стили (паддинг можно применять только к a):

140
Cordova: проблема вывода изображений по внешнему url из базы SQLite

Cordova: проблема вывода изображений по внешнему url из базы SQLite

столкнулась со следующей проблемой: вывожу из БД url в на странице, в браузере картинка отображается а в debug apk на устройстве - нетЕсли жестко...

131