Task 是一个泛型类型。这意味着如果您将类型应用于像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 线程进行,Task 函数调用位于 FX 线程之外,因此屏幕不会冻结。但是所有的绑定元素都会发生在 FX Thread 中,所以修改 GUI 是安全的。
如果您想从非 FX 线程安全地修改 GUI,只需执行以下操作:
Platform.runLater(new Runnable() {
@Override
public void run() {
//Safe modification in the FX Thread
}
});
还可以查看concurrency in JavaFX2。这更深入地解释了并发、Service、Task...
希望对你有帮助!