Индикатор прогресса не будет отображаться до тех пор, пока основной код не остановится

Я боролся в течение нескольких дней из-за глупой проблемы, и мне нужна твоя помощь. Я просто пытаюсь отобразить неопределенный индикатор процесса, как показано ниже, в отдельной стадии, в то время как мой основной код выполняет цикл. Если во время цикла выполняется определенное условие, этап выполнения должен закрыться, и основной код продолжается.

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

Я кратко объясню, что делает каждый код ниже. Как сделать так, чтобы этап загрузки отображался изначально с видимым индикатором, а затем этот этап ЗАКРЫВАЕТСЯ, когда showMessage() метод называется? По сути, я хочу показать пользователю, что происходит фоновое зацикливание, пока основной код не достигнет showMessage(),

Main.java Я не буду публиковать его, поскольку он создает только ПЕРВЫЙ GUI. Оно использует menu.fxml как ресурс в FXMLLoader... а также menu.fxml использования Controller.java в качестве контроллера.

Controller.java Этот код изменяет сцену в главном графическом интерфейсе, чтобы иметь новый макет, который просит пользователя нажать одну из видимых кнопок. Затем он проверяет, является ли кнопка источника Button1... и если это так, создайте / покажите новый этап, который использует sample.fxml как ресурс. Затем он запускает окончательный файл, Loop.java

public class Controller implements Initializable {

    public Stage loadingStage;

    @FXML
    ProgressIndicator progressIndicator;

    public void handlerButtonClick() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("field.fxml"));
        Parent rootOne = loader.load();
        ((Controller) loader.getController()).setPrimaryStage(primaryStage);
        ((Controller) loader.getController()).setPrimaryScene(scene);
        sceneField = new Scene(rootOne, 420, 510);
        primaryStage.setScene(sceneField);
        primaryStage.setTitle("Import Data");
        primaryStage.show();
    }

    public void fieldOption(ActionEvent e) throws Exception {

        source = e.getSource();
        if (source == Button1) {

            Loop loopObj = new Main();
            String[] args = {};

            //Create new stage to contain the Progress Indicator
            FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
            Parent root2 = loader2.load();
            Controller2 controller = loader2.getController();
            loadingStage = new Stage();
            loadingStage.setTitle("Loading Stage");
            Scene scene = new Scene(root2, 200, 200);
            loadingStage.setScene(scene);
            loadingStage.show();

            //Runs the looper
            loopObj.start(stage);
        }

    }

Sample.fxml

Этот код создает индикатор прогресса и использует контроллер Controller2

<AnchorPane prefHeight="200.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml/1"
            xmlns="http://javafx.com/javafx/2.2" fx:controller="Controller2">
    <children>
        <ProgressIndicator fx:id="progressIndicator" layoutX="78.0" layoutY="55.0" progress="-1.0"/>
    </children>
</AnchorPane>

Controller2.java Этот код реализует Initializable чтобы сделать индикатор прогресса видимым:

public class Controller2 implements Initializable {
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        ProgressIndicator progressIndicator = new ProgressIndicator();
        progressIndicator.setVisible(true);
    }
}

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

public class Loop extends Application {
    @Override
    public void start(Stage ignored) throws Exception {
        Platform.setImplicitExit(false);
        for (int i = 0; i <= 100; i++) {
            if (i == 75){
                saveAttachment("Hello");
            }
        }
    }

    public static void saveAttachment(String subject) throws IOException, MessagingException {
        showMessage(subject);
    }

    private static void showMessage(String subject) throws IOException, MessagingException {
        // Close the loading stage here.
    }
}

Обратите внимание, как он использует public void start(Stage ignored), Main.java использует public void start(Stage primaryStage), Возможно, это плохо. Я так расстроен, пожалуйста, помогите!

ОБНОВИТЬ

Я применил предложения Брайана, и в Controller.java добавили новую задачу так:

 Stage loadingStage = new Stage();

           //create task object
           Task<Void> task = new Task<Void>(){
               @Override
               protected Void call() throws Exception{
                   System.out.println("Background task started...");
                   FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
                   Parent root2 = loader2.load();
                   Controller2 controller = loader2.getController();
                   loadingStage.setTitle("Hello World");
                     Scene scene = new Scene(root2, 450, 250);
                   System.out.println("HERE6");
                   loadingStage.setScene(scene);
                   System.out.println("HERE7");
                   loadingStage.show();
                   System.out.println("HERE8");
                   return null;
               }
           };

           Thread th = new Thread(task);
           th.setDaemon(true);
           System.out.println("Starting background task...");
           th.start();

Проблема сейчас в том, что она не доходит до строки распечатки с надписью "ЗДЕСЬ7". Он успешно входит в задачу и продолжает основной код, но задача не выходит за пределы того места, где печатается "ЗДЕСЬ6", поэтому новый этап не открывается. Что дает?

1 ответ

В Ctlr2 у вас есть ProgressIndicator progressIndicator = new ProgressIndicator(); но если он находится в файле FXML, вы не создаете новый. Просто делать @FXML ProgressIndicator progressIndicator; как у вас в первом Ctlr почему-то??

Но это не решит вашу проблему, вы запускаете все в потоке приложений JavaFX (поток GUI). Вероятно, что происходит (я действительно не читал код), это то, что вы делаете обе вещи в одном и том же потоке, а индикатор прогресса должен ждать завершения main, а затем он может обновить GUI. Вы ставите метки для задачи и параллелизма, это то, что вам нужно.

Проверьте здесь и выполните поиск других примеров. /questions/24058127/indikator-vyipolneniya-v-javafx/24058132#24058132

Другие вопросы по тегам