Multithreading Javafx任务<;可观察列表>;。updateValue仅触发第一个更改事件
我希望观察任务的valueProperty,并在它被updateValue()更改时采取操作。不过,更改事件似乎只在第一次更新时触发 有一节暗示重复调用UpdateValue以返回部分结果是合乎礼仪的。也许我不明白他们所说的“更新合并”是什么意思 最低限度的例子Multithreading Javafx任务<;可观察列表>;。updateValue仅触发第一个更改事件,multithreading,javafx,javafx-8,Multithreading,Javafx,Javafx 8,我希望观察任务的valueProperty,并在它被updateValue()更改时采取操作。不过,更改事件似乎只在第一次更新时触发 有一节暗示重复调用UpdateValue以返回部分结果是合乎礼仪的。也许我不明白他们所说的“更新合并”是什么意思 最低限度的例子 导入javafx.application.application; 导入javafx.application.Platform; 导入javafx.beans.property.ReadOnlyObjectWrapper; 导入java
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.ReadOnlyObjectWrapper;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.concurrent.Task;
导入javafx.scene.scene;
导入javafx.scene.control.ListView;
导入javafx.stage.stage;
公共类主扩展应用程序{
MyTask任务=新建MyTask();
ListView ListView=新建ListView();
@凌驾
public void start(Stage primaryStage)引发异常{
primaryStage.setScene(新场景(listView));
primaryStage.show();
线程任务线程=新线程(任务);
taskThread.start();
task.valueProperty().addListener((ob,old,nw)->listView.getItems().addAll(nw));//仅激发一次。
//task.lastString.addListener(iv->listView.getItems().addAll(task.lastString.getValue());//激发每个添加
}
公共静态void main(字符串[]args){launch(args);}
}
类MyTask扩展了任务{
ObservableList=FXCollections.observableArrayList();
public ReadOnlyObjectWrapper lastString=new ReadOnlyObjectWrapper(new String());
整数maxWork=4;
@凌驾
受保护的ObservableList调用()引发异常{
对于(整数stringNo=0;stringNo{
lastString.setValue(addMe);//按预期工作。
} );
}
退货清单;
}
}
任务的值只更改一次。最初它是null
。在第一次迭代中,它会发生变化,因此值==list
,在每个后续迭代中,值==list
(即没有进一步的变化)
您可能想:
通过调用Platform.runLater(()->list.add(addMe)),更新FX应用程序线程上的列表代码>
安排观察列表本身,而不是任务的值
属性
对于稍后出现的任何人,下面是代码,经过修改以提供对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));
}
}
});
}
}
软件包演示;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.ReadOnlyObjectWrapper;
导入javafx.collections.FXCollections;
导入javafx.collections.ListChangeListener;
导入javafx.collections.ObservableList;
导入javafx.concurrent.Task;
导入javafx.scene.scene;
导入javafx.scene.control.ListView;
导入javafx.stage.stage;
导入java.util.List;
公共类主扩展应用程序{
MyTask任务=新建MyTask();
ListView ListView=新建ListView();
@凌驾
public void start(Stage primaryStage)引发异常{
primaryStage.setScene(新场景(listView));
primaryStage.show();
task.lv=列表视图;
线程任务线程=新线程(任务);
taskThread.start();
}
公共静态void main(字符串[]args){
发射(args);
}
}
类MyTask扩展了任务{
ObservableList=FXCollections.observableArrayList();
public ReadOnlyObjectWrapper lastString=new ReadOnlyObjectWrapper(new String());
整数maxWork=4;
ListView lv;
@凌驾
受保护的ObservableList调用()引发异常{
updateValue(list);//确保任务的valueproperty具有值。
Platform.runLater(()->addMyListener());
对于(整数stringNo=0;stringNo{
lastString.setValue(addMe);//按预期工作。
});
}
退货清单;
}
void addMyListener(){
ObservableList obl=valueProperty().getValue();
obl.addListener(新的ListChangeListener(){
@凌驾
public void onChanged(change谢谢!你说得很对,我把任务的valueProperty误认为是任务的ObserveableList。最初的回答是:“这是代码,修改后可以直接访问列表视图本身”。为什么MyTask应该知道一些GUI元素?!这不是它的责任。紧密耦合会使架构消失,而这样做会使代码库的维护变成噩梦……重点是。MCVE不关心架构。
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));
}
}
});
}
}