首先,我是JavaFX的新手,很抱歉,如果這個問題很愚蠢。我如何從任務中獲取返回對象?如何從任務內設置Var?
我的繼承人問題:
我想從一個模擬對象的名單。模擬從1到5秒延遲。但我不想,我的GUI在這個時候凍結。
在Java.Swing中,使用Thread很容易,但據我所知,JavaFX具有Tasks。
我讀過很多教程,但無處不在,他們返回一個文本屬性。所以這裏是我的問題:我如何設置一個對象的值與任務/線程(在我的情況下是一個列表)的計算結果
謝謝。
首先,我是JavaFX的新手,很抱歉,如果這個問題很愚蠢。我如何從任務中獲取返回對象?如何從任務內設置Var?
我的繼承人問題:
我想從一個模擬對象的名單。模擬從1到5秒延遲。但我不想,我的GUI在這個時候凍結。
在Java.Swing中,使用Thread很容易,但據我所知,JavaFX具有Tasks。
我讀過很多教程,但無處不在,他們返回一個文本屬性。所以這裏是我的問題:我如何設置一個對象的值與任務/線程(在我的情況下是一個列表)的計算結果
謝謝。
雷,
你是正確的,該例子似乎掩蓋從任務找回結果。有兩種方法,你可以得到返回結果,我知道:
getValue()
方法(這是我做的方式)get()
方法類(我沒有使用過,但原則上它應該可以工作)。隨着第一getValue()
形式給出,你需要確保任務將通過在任務的調用方法updateValue(...)
方法的價值。然後把聽者的WorkerStateEvent
myTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@SuppressWarnings("unchecked")
@Override
public void handle(WorkerStateEvent event) {
ReturnType rt = (ReturnType) event.getSource().getValue()
// ... other stuff to do here ...
}
});
第一種方法是有點冗長,但它的工作原理,並允許一些更復雜的操作任務完成後。
第二種方法稍微簡單明瞭,但不會給予您在任務完成時控制該做什麼的太多控制。使用FutureTask的get()
方法,代碼應該阻塞,直到任務返回值爲止。
//
// Start the task in a thread (using whatever approach you like)
//before calling the get() method.
//
ReturnType rt = myTask.get();
我已經使用Future
對象與其他代碼,但我沒用過FutureTask
與FX API,所以我不能告訴你,如果有隱藏的陷阱在裏面:所以用它作爲應儘可能簡單。
祝你好運,
chooks
的任務是一個通用型。這意味着如果您將類型應用於像Task<Integer>
這樣的任務,Task類將具有返回Integer的函數。其中一個功能是valueProperty()
,可以綁定到其他場景元素。顯示在一個標籤,或任何其他。我建議你閱讀the javafx binding tutorial,以獲得更好的理解。
以下是任務使用或其屬性的示例。
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TestingTasks extends Application{
public static void main(String[] args) {launch(args);}
@Override
public void start(Stage stage) throws Exception {
VBox vbox = new VBox(10);
vbox.setAlignment(Pos.TOP_CENTER);
ListView<String> list = new ListView<>();
HBox hbox = new HBox(10);
hbox.setAlignment(Pos.CENTER_LEFT);
Label labelMessage = new Label();
hbox.getChildren().addAll(new Label("Message: "), labelMessage);
ProgressBar progress = new ProgressBar(-1);
progress.setVisible(false);
Button button = new Button("Executing Task");
button.setOnAction(event(button, list, progress, labelMessage));
vbox.getChildren().addAll(list, hbox, button, progress);
Scene scene = new Scene(vbox, 400, 300);
stage.setScene(scene);
stage.show();
}
private EventHandler<ActionEvent> event(final Button button, final ListView<String> list, final ProgressBar progress, final Label labelMessage) {
return new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Task<ObservableList<String>> task = generateTask();
list.itemsProperty().bind(task.valueProperty());
progress.visibleProperty().bind(task.runningProperty());
labelMessage.textProperty().bind(task.messageProperty());
button.disableProperty().bind(task.runningProperty());
task.runningProperty().addListener(listenerRunningTask());
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
}
};
}
private Task<ObservableList<String>> generateTask() {
return new Task<ObservableList<String>>() {
@Override
protected ObservableList<String> call() throws Exception {
updateMessage("Waiting...");
Thread.sleep(5000);
updateMessage("Waking up");
return FXCollections.observableArrayList("One", "Two", "Three");
}
};
}
private ChangeListener<? super Boolean> listenerRunningTask() {
return new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(oldValue && !newValue){
//TODO when finish
}
}
};
}
}
因此,基本上,你可以在任務返回一個變量,或者等待任務結束,並執行一些東西,建立自己的綁定...
如果你想修改從屏幕上的東西線程,你需要從FX線程完成,任務函數調用在FX線程之外,因此屏幕不會凍結。但所有綁定元素都將出現在FX線程中,因此可以安全地修改GUI。
如果你想從一個不FX線程安全地修改GUI,只是做:
Platform.runLater(new Runnable() {
@Override
public void run() {
//Safe modification in the FX Thread
}
});
也採取concurrency in JavaFX2看看。這更深入地解釋了併發性,服務,任務...
希望它有幫助!
感謝您的回答,我發現我的錯誤。如果任務完成,我忘了添加一個EventHandler。所以我把allways稱爲task.getValue(),但Task仍然是runnig,所以值爲空。 – ray