2016-03-22 9 views
-2

Ich habe eine Interface-Methode, die ein Future-Objekt zurückgeben soll.Wie benutzt man FutureTask <V>, auf ein Event wartend?

Future<Result> doSomething() 

Die Implementierung dieser Methode zeigt einige ui (javafx). Eines der UI-Elemente hat einen Listener, der aufgerufen werden muss, um das eigentliche Ergebnis zu erhalten, das ich brauche.

Wie erreiche ich das? Gibt es eine bessere Lösung?

Hier ist ein Beispiel Aktion Ich muss warten:

// this is some framework method I cannot change 
@Override 
public Data execute(Data data) { 
    Future<Data> dataFuture = handler.doSomething(data); 
    // this should basically wait until the user clicked a button 
    return dataFuture.get(); 
} 

// handler implementation 
public Future<Data> doSomething(Data data) { 
    // the question is how to implement this part, to be able to 
    // return a future object 
    Button button = new Button("Wait until click"); 
    // create thread that waits for the button click ?!???? 
    // modify incoming data object when the button was clicked 
    // somehow create the Future object that's bound to the button click 
    return future; 
} 

Dies ist, was ich erreichen will:

  1. meine Methode doSomething eine neue Szene zeigt (ui) mit einem Knopf auf sie
  2. und kehrt immedeately die Zukunft Objekt
  3. future.get() wartet, bis der Benutzer auf die Schaltfläche
  4. gedrückt

Einschränkungen: es ohne zusätzliche Bibliothek getan werden muss und auf> = Java7

+0

Siehe auch http://stackoverflow.com/questions/13796595/return-result-from-javafx-platform-runlater –

+0

erreichen wollen Wo Wird diese Methode aufgerufen? (Der FX-Anwendungsthread oder ein Hintergrundthread?) Warum müssen Sie die Dinge so machen (d. H. Warum verwenden Sie nicht einfach die üblichen ereignisgesteuerten Mechanismen für "etwas tun, wenn eine Taste gedrückt wird")? Wo wird der Button angezeigt? In einem Dialog? In einer bestehenden Phase? Sie müssen wahrscheinlich * viele * weitere Details angeben oder vorzugsweise ein komplettes ausführbares Beispiel, um zu verdeutlichen, was Sie zu tun versuchen. –

Antwort

0

Verwenden Sie ein javafx.concurrent.Task. Es stammt von FutureTask. Es gibt umfangreiche Beispiele im verknüpften Javadoc zur Task-Verwendung.

Oracle auch ein Tutorial, das Task-Nutzung diskutiert:

Ich denke, das ist das, was Sie wollen, aber ich kann die Frage verstanden haben, wenn ja, bearbeiten Sie bitte die Frage ein bisschen, um Anforderungen zu klären (vielleicht mit einem mcve). Das Etwas, das mich etwas unsicher macht, ist der Teil in deinem Titel "Warte auf dein Event?", Ich bin mir nicht sicher, was das in diesem Zusammenhang bedeutet.

+0

Ich hoffe, das Beispiel ist jetzt besser. – andre

+0

Leider ist es mir immer noch etwas unklar, es fehlt noch eine Menge an deinem Beispiel. Concurrency-Konstrukte wie FutureTask sind nur dann sinnvoll, wenn tatsächlich gleichzeitig Arbeiten ausgeführt werden (die Anwendung ist multi-threaded), aber Ihr Beispiel erstellt keine Threads. Ich frage mich also, ob Sie wirklich eine FutureTask benötigen oder ob Sie nur versuchen, einen asynchronen Callback zu erhalten (den Sie bereits im Action-Event-Handler für Ihre Schaltfläche haben). Wenn Sie ein vollständiges Programm bereitstellen, das jemand kopieren und einfügen kann, um es auszuführen, ist es möglicherweise leichter zu verstehen. – jewelsea

+0

aktualisiert das Beispiel mit ein wenig mehr Code – andre

-1

Dies ist eine Lösung, nach der ich gesucht habe. Es ist nicht sehr nett, da das Thread.sleep mich nicht überzeugt.

aber jetzt Sie propably eine Vorstellung von dem, was ich

// make sure this is not called on the ui thread 
public Future<Data> doSomething(Data data) { 
    WaitingFuture future = new WaitingFuture(data); 
    Platform.runLater(() -> { 
       Button button = new Button("Wait until click"); 
       button.setOnAction(future); 
       // show button on ui... 
      }); 
    favouriteExecutorService.submit(future); 
    return future; 
} 

static class WaitingFuture extends Task<Data> implements EventHandler<ActionEvent> { 
    private Data data; 

    WaitingFuture(Data originalData) { 
     this.data = originalData; 
    } 

    private Data waitingData; 

    @Override 
    public void handle(ActionEvent event) { 
     waitingData = data.modify(); 
    } 

    @Override 
    protected Data call() throws Exception { 
     while (waitingData == null) { 
      Thread.sleep(100); 
     } 
     return waitingData; 
    } 
}