34

私はjavafxアプリケーションと、javafx.concurrent.Task一連のファイルを圧縮してアップロードする長いプロセスを実行する、を介して実装されたワーカースレッドを持っています。
経由でタスクの進行状況を進行状況バーに接続しましたprogressProperty
これに加えて、処理中のアイテムに関する詳細な状態を UI に報告したいと考えています。つまり、処理中のファイルの名前とそのサイズ、および単一ファイル処理で発生する可能性のあるエラーです。
これらの情報を使用して UI を更新することは、ワーカー スレッドからは実行できません。せいぜい、同期されたコレクションに追加できます。
しかし、新しいデータが利用可能であることを UI に通知するイベントが必要です。
javafx には、この問題に対する特定のサポートがありますか?

更新、より良い処方

Platform.runLater としてアドホックなクロススレッド メカニズムを設計する代わりに、各プロパティを他のスレッドからリッスンできるようにしようとしています。Task によって提供される runningProperty および stateProperty と同じように

4

2 に答える 2

39

エラー処理を自分で処理する必要があると私が言える限り、私は同様の問題に遭遇しています。私の解決策は、メソッド呼び出しを介して UI を更新することです。

何かのようなもの:

  try
  {
    //blah...
  }
  catch (Exception e)
  {
    reportAndLogException(e);
  }
  ...
  public void reportAndLogException(final Throwable t)
  {
    Platform.runLater(new Runnable() {
      @Override public void run() {
        //Update UI here     
      }
    });
  }

基本的に、更新のために手動で UI スレッドに戻すだけです (ほとんどの他のフレームワークで行うように)。

于 2012-07-27T15:37:22.627 に答える
7

この回答は、ダニエルの回答と同じ概念を使用しています。

同封されているのは、 Task javadocの Partial Result サンプルのコピーです(現在 Java 8 javadoc に埋め込まれている構文エラーを修正し、より具体的なジェネリック型を追加しています)。その変更を使用できます。

例外を partialResults コレクションに配置します。あなたのケースでは、タスクから例外のリストを返す必要はありませんが、代わりに、例外を表示する UI コントロールにそれらを配置できます (例外表示用ListViewのなどCellFactory)。partialResults コレクションは常に更新され、JavaFX UI スレッドでアクセスされるため、同期する必要がないことに注意してください (更新はPlatform.runLater()Daniel のソリューションと同様の呼び出しを介して行われます)。

public class PartialResultsTask extends Task<ObservableList<Rectangle>> {
    private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults =
            new ReadOnlyObjectWrapper<>(
                    this, 
                    "partialResults",
                    FXCollections.observableArrayList(
                            new ArrayList<>()
                    )
            );

    public final ObservableList<Rectangle> getPartialResults() {
        return partialResults.get();
    }

    public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() {
        return partialResults.getReadOnlyProperty();
    }

    @Override
    protected ObservableList<Rectangle> call() throws Exception {
        updateMessage("Creating Rectangles...");
        for (int i = 0; i < 100; i++) {
            if (isCancelled()) break;
            final Rectangle r = new Rectangle(10, 10);
            r.setX(10 * i);
            Platform.runLater(() -> partialResults.get().add(r));
            updateProgress(i, 100);
        }
        return partialResults.get();
    }
}

監視可能なプロパティを更新するとき、タスクは最初に更新が FX アプリケーション スレッドで発生しているかどうかを確認します。存在する場合は、即時更新を行います。そうでない場合は、呼び出しで更新をラップしPlatform.runLater()ます。これがどのように行われるかを理解するには、タスクのソース コードを参照してください。

おそらく、一連の一般的な同時実行対応プロパティを定義することは可能ですが、JavaFX はそのような機能をコアに提供していません。実際、その必要はありません。javafx.concurrent パッケージを除いて、JavaFX はシングルスレッドの UI フレームワークです。

于 2012-07-27T17:32:06.093 に答える