2017-04-06 13 views
0

コンソールとGUIで実行可能で更新可能なタスクがあります。期待とGUIが更新されますように私のJavaFX GUI内の進捗状況やメッセージプロパティを接着してコンソールではなくGUIで変更リストが起動される

 public static Task<Void> doStuff() { 
    Task<Void> task; 
    task = new Task<Void>() { 
     final int totalSteps = 4; 
     @Override 
     public Void call() throws Exception { 

      updateProgress(0, totalSteps); 
      updateMessage("1"); 
      action(1); 
      updateProgress(0, totalSteps); 
      updateMessage("2"); 
      action(2); 
      //etc.. 
      return null; 
     } 
    }; 
    new Thread(task) 
      .start(); 
    return task; 
} 

として書かれた私のタスクを考えてみましょう、すべてが進捗に応じて動作します。私のCLI内 が、私はデバッグに見ることができるような単純なプログレスバーのウィッヒは限り操作の進捗状況

private static void progressBar(Task task) { 

    task.progressProperty().addListener((new ChangeListener() { 
     @Override 
     public void changed(ObservableValue observable, Object oldValue, Object newValue) { 
      // Return to line beginning 
      System.out.print("\r"); 
      int percentage = (int) (100 * task.progressProperty().get()); 
      System.out.format("[%3d%%] %s", percentage, task.messageProperty().get()); 

      if (percentage == 100) { 
       System.out.println("Finished"); 
      } 
     } 
    })); 

} 

}

についてのユーザーの更新を構築しようとした、変更リスナーは、メソッドが取得することはできません変更しましたトリガーされた。何を私は間違って設定しましたか?終わりの完成した印刷物さえも書かれません。

+1

CLIの例をどのように実行しますか? 'Task'クラスはFXスレッドと連携するように設計されているので、FX UIスレッドが存在しないため、JavaFXインフラストラクチャが初期化されていない場合、進行状況の更新やメッセージを出力しない可能性があります。 – Itai

+0

CLIが開始されましたStandart Javaとしてのメインクラススレッド内でProgress Barを呼び出そうとしましたが、これはどちらもうまくいきませんでした。では、JavaFXスレッドとしてCLIを起動する必要がありますか?これは、GUIではない環境でも可能でしょうか? – chenino

+1

可能かどうかは分かりませんが、たとえあったとしてもそれはおそらく望ましくありません。 'Task'はJavaFXと密接に結びついているようで、JavaFXなしで作業するソリューションが必要な場合は、' Task'を使用しないことを検討するべきでしょう。 – Itai

答えて

0

コメントに記載されているように、JavaFX Taskのプロパティの更新は、FXアプリケーションスレッドで実行されます。このスレッドは、JavaFXシーングラフのレンダリングに使用されるスレッドで、起動時にJavaFXツールキットによって開始されます。 JavaFXツールキットが実行されていない場合、スレッドは開始されず、それらのプロパティは更新されません。

JavaFXアプリケーションの外部で機能する必要があるバックグラウンドで実行できるものが必要な場合は、JavaFXに依存しないスレッド機能を使用する必要があります。この場合、単にRunnableまたはCallableを実装することができます。状態が変更されたときに通知を提供する場合は、状態が変更されたときに呼び出されるコールバックを作成します。コールバックは、java.util.functionパッケージのインターフェイスを使用して表現するのが最適です。

あなたが表示する場合は、本当にメッセージと進行が一緒に必要なように見えるので、おそらくBiConsumer<String, Integer>を使用できます。

public class DoStuff implements Runnable { 

    private final int totalSteps ; 
    private BiConsumer<String, Integer> update ; 

    public DoStuff(int totalSteps) { 
     this.totalSteps = totalSteps ; 
    } 

    public void setUpdate(BiConsumer<String Integer> update) { 
     this.update = update ; 
    } 

    @Override 
    public void run() { 
     if (update != null) { 
      update.accept("0", 0) ; 
     } 
     for (int i = 1 ; i <= totalSteps ; i++) { 
      action(i); 
      if (update != null) { 
       update.accept(Integer.toString(i), i); 
      } 
     } 
    } 

    private void action(int i) { 
     // ... 
    } 

    public int getTotalSteps() { 
     return totalSteps() ; 
    } 
} 

、今、あなたは

public void progressBar(DoStuff doStuff) { 
    doStuff.setUpdate((s, p) -> { 

     // Return to line beginning 
     System.out.print("\r"); 
     int percentage = 100 * p/doStuff.getTotalSteps(); 
     System.out.format("[%3d%%] %s", percentage, s); 

     if (percentage == 100) { 
      System.out.println("Finished"); 
     } 
    }); 
} 

だろうし、あなたがJavaFXの環境でこれを使用したい場合は

new Thread(doStuff).start(); 

でバックグラウンドスレッドでこれを実行し、次のことができますが、コールバックがFXアプリケーションスレッドのUIコンポーネントを更新していることを確認してください。

DoStuff doStuff = ... ; 
doStuff.setUpdate((s, p) -> Platform.runLater(() -> { 
    label.setText(s); 
    double progress = 1.0 * p/doStuff.getTotalSteps(); 
    progressBar.setProgress(p); 
})); 

それは、これをラップTask<Void>を作成することも合理的に簡単だし、いつものJavaFXの方法で進捗状況やメッセージを公開します。

DoStuff doStuff = ... ; 
Task<Void> doStuffTask = new Task<Void>() { 
    @Override 
    protected Void call() { 
     doStuff.setUpdate((s, p) -> { 
      updateProgress(p, doStuff.getTotalSteps()); 
      updateMessage(s); 
     }); 
     doStuff.run(); 
     return null ; 
    } 
}; 

そして、いつものように

progressBar.progressProperty().bind(doStuffTask.progressProperty()); 
label.textProperty().bind(doStuffTask.messageProperty()); 

Thread t = new Thread(doStuffTask); 
t.setDaemon(true); 
t.start(); 

を行います。

関連する問題