我想观察任务的valueProperty,并在updateValue()更改时执行操作。改变事件似乎只是在第一次更新时被触发了。
Oracle's getValue document有一个部分暗示重复调用UpdateValue以返回部分结果是犹太的。也许我不理解“更新合并”的含义。
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
public class Main extends Application {
MyTask task = new MyTask();
ListView<String> listView = new ListView<>();
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(listView));
primaryStage.show();
Thread taskThread = new Thread(task);
taskThread.start();
task.valueProperty().addListener( (ob,old,nw) -> listView.getItems().addAll(nw) ); // Only fires once.
//task.lastString.addListener( iv -> listView.getItems().addAll(task.lastString.getValue()) ); // Fires every add
}
public static void main(String[] args) { launch(args); }
}
class MyTask extends Task<ObservableList<String>> {
ObservableList<String> list = FXCollections.observableArrayList();
public ReadOnlyObjectWrapper<String> lastString = new ReadOnlyObjectWrapper<>(new String());
Integer maxWork = 4;
@Override
protected ObservableList<String> call() throws Exception {
for( Integer stringNo=0; stringNo<maxWork; stringNo++) {
Thread.sleep(500);
String addMe = new String("Thread string " + stringNo);
list.add(addMe);
updateProgress(stringNo, maxWork);
updateValue(list); // Only fires one change event
Platform.runLater( () -> {
lastString.setValue(addMe); // Works as expected.
} );
}
return list;
}
}
答案 0 :(得分:4)
任务的value
只会更改一次。最初是null
。在第一次迭代时,它会更改value==list
以及每次后续迭代value==list
(即没有进一步的更改)。
你可能想:
Platform.runLater(() -> list.add(addMe));
value
属性。答案 1 :(得分:3)
对于后来出现的人来说,这里的代码经过修改后可以直接访问listView本身。
package demo;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import java.util.List;
public class Main extends Application {
MyTask task = new MyTask();
ListView<String> listView = new ListView<>();
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(listView));
primaryStage.show();
task.lv = listView;
Thread taskThread = new Thread(task);
taskThread.start();
}
public static void main(String[] args) {
launch(args);
}
}
class MyTask extends Task<ObservableList<String>> {
ObservableList<String> list = FXCollections.observableArrayList();
public ReadOnlyObjectWrapper<String> lastString = new ReadOnlyObjectWrapper<>(new String());
Integer maxWork = 4;
ListView lv;
@Override
protected ObservableList<String> call() throws Exception {
updateValue(list); // make sure that the task's valueproperty has a value.
Platform.runLater(() -> addMyListener());
for (Integer stringNo = 0; stringNo < maxWork; stringNo++) {
Thread.sleep(500);
String addMe = new String("Thread string " + stringNo);
list.add(addMe);
updateProgress(stringNo, maxWork);
updateValue(list); // Only fires one change event
Platform.runLater(() -> {
lastString.setValue(addMe); // Works as expected.
});
}
return list;
}
void addMyListener() {
ObservableList<String> obl = valueProperty().getValue();
obl.addListener(new ListChangeListener<String>() {
@Override
public void onChanged(Change<? extends String> c) {
while (c.next()) {
List added = c.getAddedSubList();
Platform.runLater(() -> lv.getItems().addAll(added));
}
}
});
}
}