2015-12-13 8 views
0

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

enter image description here

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

Я кратко объясню, что делает каждый код ниже. Как это сделать так, чтобы начался этап загрузки с видимым индикатором, а затем этот этап ЗАКРЫТСЯ, когда вызывается метод 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). Возможно, это плохо. Я так расстроен, пожалуйста, помогите!

UPDATE

Я применил предложения Брайана, и в 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(); 

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

+0

Вы не можете обновить пользовательский интерфейс в фоновом потоке, поэтому он генерирует исключение в 'loadStage.setScene (...)'. Но я не понимаю, почему вы так делаете эту часть в фоновом потоке. Наверняка это цикл 'for' со всеми вызовами' saveAttachment', который занимает много времени? Возможно, прочитайте мой ответ на http://stackoverflow.com/questions/30249493/using-threads-to-make-database-requests для получения некоторой исходной информации. Документы API '' Task' (http://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html) полны примеров. –

+0

Спасибо, я сейчас занимаюсь ремеслом и чтением. Отчитается. –

+0

Я дошел до того, что сцена открылась правильно, но я узнал, что для этой цели требуется «FutureTask». –

ответ

2

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

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

Проверьте здесь и выполните поиск других примеров. https://stackoverflow.com/a/22847734/2855515

+0

Спасибо, Брайан, я сейчас на правильном пути. Я обновил свой вопрос (см. Очень низкое). Он успешно входит в задачу, но не создает или не демонстрирует новый этап. Он просто зависает после записи «Начальная задача», а основной код продолжается. Что не так? –

+0

На самом деле, он не выйдет за пределы, где говорится «ЗДЕСЬ6». По какой-то причине строка 'loadStage.setScene (scene);' вызывает остановку. –

 Смежные вопросы

  • Нет связанных вопросов^_^