javafx, update ui à partir d'un autre thread

j'ai une application javafx, et un thread worker, implémenté via javafx.concurrent.Task, qui effectue un long processus, qui est la compression et de télécharger un ensemble de fichiers.

J'ai relié la progression de la tâche à une barre de progression via progressProperty.

en plus de cela, je veux qu'un état détaillé au sujet de l'article en cours de traitement soit déclaré dans l'ui. Qui est, le nom du fichier à traiter, ainsi que sa taille et les erreurs qui peuvent résulter du seul fichier processus.

La mise à jour de L'UI avec ces informations ne peut pas être faite à partir du thread worker, tout au plus je peux l'ajouter à une collection synchronisée.

Mais j'ai ensuite besoin d'un événement pour informer L'IU que de nouvelles données sont disponibles.

Javafx a-t-il un support spécifique pour cette question?

mise à jour, la meilleure formulation

au lieu de concevoir un mécanisme ad hoc de croisement comme plate-forme.runLater, j'essaie de permettre à chacun propriété à écouter depuis d'autres fils. Tout comme runningProperty et stateProperty fournis par la tâche

28
demandé sur AgostinoX 2012-07-27 19:12:28

2 réponses

je rencontre un problème similaire, autant que je puisse dire que vous avez à faire face à la manipulation de l'erreur vous-même. Ma solution est de mettre à jour l'INTERFACE utilisateur par l'intermédiaire d'un appel de méthode:

quelque Chose comme:

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

essentiellement, je le renvoie manuellement au Thread de L'interface utilisateur pour une mise à jour (comme je le ferais dans à peu près n'importe quel autre framework).

29
répondu Daniel B. Chapman 2012-07-27 15:37:22

cette réponse utilise le même concept que la réponse de Daniel.

vous trouverez ci-joint une copie de l'exemple de résultat partiel de tâche javadoc (corrigé pour les erreurs de syntaxe actuellement intégrées dans le javadoc Java 8 et pour ajouter des types génériques plus spécifiques). Vous pouvez utiliser une modification de la.

placez vos exceptions dans la collection partialResults. Pour votre cas, vous n'avez pas besoin de retourner la liste des exceptions de la Tâche, mais peut, au lieu de les placer dans certains Contrôle UI qui affiche les exceptions (comme un ListView avec un CellFactory pour l'affichage d'exception). Notez que la collection partialResults n'a pas besoin d'être synchronisée car elle est toujours mise à jour et accessible sur le thread JavaFX UI (la mise à jour se fait via un Platform.runLater() appel similaire à la solution de 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();
    }
}

lors de la mise à jour, la tâche propriétés observables vérifie d'abord si la mise à jour se produit sur le thread D'Application FX. Si elle est, il effectue une mise à jour immédiate. Si ce n'est pas le cas, alors il enroule la mise à jour dans un Platform.runLater() appel. Voir le code source de la tâche comprendre comment cela se fait.

peut-être serait-il possible de définir un ensemble de propriétés génériques simultanées conscientes, mais JavaFX ne fournit pas de telles installations à son cœur. En effet, il n'est pas nécessaire. À l'exception de la javafx.paquet concurrent, JavaFX est un seul framework threaded UI.

6
répondu jewelsea 2015-12-14 23:36:28