我想在后台运行一个任务,更新视图中的中间结果。我正在尝试实现 MVC JavaFX 应用程序。任务在模型中定义。
我想将部分结果发送给主要威胁,以便在视图中显示它们。
我使用 updateValue() 来执行此操作。另外,我在控制器中定义了对象属性和侦听器。
我的问题:每次在任务中执行 updateValue() 时,不会触发侦听器的方法changed()。为什么?我怎样才能强迫它这样做?
我还没有找到太多复杂的例子。
到目前为止我所拥有的:
模型.cpp
ComplexObject _complexO;
public Task<ComplexObject> getModelTask() {
return new Task<ComplexObject>() {
@Override
protected ComplexObject call() throws Exception {
int numberOfFiles = 0;
boolean filesToRead = true;
while (filesToRead){
// ....
_complexO = new ComplexObject();
try{
//..
if(f.exists()){
_complexO.initialize();
numberOfScans ++;
}
else{
_complexO.initializeToNull();
}
String stringNumber = Converter.toString(numberOfFiles);
updateMessage(stringNumber);
updateValue(_complexO );
} catch(Exception ex){
ex.printStackTrace();
_complexO = null;
return _complexO;
}
filesToRead = areThereFilesToRead();
}
return _complexO;
}
};
}
控制器.cpp
...
Task< ComplexObject> task = _model.getModelTask();
_AJavaFXTextField.textProperty().bind(task.messageProperty());
_AJavaFXTextField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue observable, String oldValue, String newValue) {
System.out.println("Success with messageProperty!!" + newValue);
}
});
SimpleObjectProperty<ComplexObject> complexObjectProperty = new SimpleObjectProperty<>();
complexObjectProperty.bind(task.valueProperty());
complexObjectProperty.addListener(new ChangeListener<ComplexObject>(){
@Override
public void changed(ObservableValue<? extends ComplexObject> observable, ComplexObject oldValue, ComplexObject newValue) {
if(newValue.data == null ) {
System.out.println("value is new!!! " + scansNumber);
}
else if(newValue.isValid()){
System.out.println("I want to plot newValue data here");
}
}
});
Thread th= new Thread(task);
System.out.println("call TASK");
th.start();
}
我的问题/结论在这里:
如何强制我在任务 updateValue() 中执行的所有时间都真正执行侦听器 - 因此在我想要绘制数据的位置执行代码。
为什么 messageProperty 的触发绑定次数比 valueProperty 的触发次数多? - 应该是相同的次数。
为什么我发现侦听器代码在调试模式下比正常执行时被触发的次数更多?
任何关于这个主题的好资源的推荐(从复杂的角度来看)都会很棒。
我正在寻找 JavaFX 中的某些东西来替代 SwingWorker。
最后我真正想要的是:从任务中返回复杂对象的列表,理想情况下, updateValue() 会逐个发送对象(部分结果)
我已经关注:https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html
非常感谢您的任何贡献
Task
仅保证值传递给updateValue
或者稍后传递的值将被设置为value
财产。这样做是为了通过限制侦听器收到通知的更改数量来提高应用程序线程的性能。
为什么更多次触发绑定messageProperty
比valueProperty
? - 应该是相同的次数。
如上所述,根本无法保证更新的数量。
为什么我发现侦听器代码在调试模式下比正常执行时被触发的次数更多?
一般来说,调试会使你的程序更小。您的线程的更新频率越小Task
,两次之间的更新次数越少Task
类更新的属性越少,跳过的次数越多。 (更新可能每帧或每几帧执行一次。)如果您甚至在任务中使用断点/步进器,您可能会执行Task
当应用程序线程以正常速度运行时速度非常慢。
它应该很容易实现publish
自行使用List
缓冲更新
public abstract class JavaFXWorker<S, T> extends Task<S> {
private List<T> chunks = new ArrayList<>();
private final Object lock = new Object();
private boolean chunkUpdating = false;
protected final void publish(T... results) {
synchronized (lock) {
chunks.addAll(Arrays.asList(results));
if (!chunkUpdating) {
chunkUpdating = true;
Platform.runLater(() -> {
List<T> cs;
synchronized (lock) {
cs = chunks;
// create new list to not unnecessary lock worker thread
chunks = new ArrayList<>();
chunkUpdating = false;
}
try {
process(cs);
} catch (RuntimeException ex) {
}
});
}
}
}
protected void process(List<T> chunks) {
}
}
样品使用
@Override
public void start(Stage primaryStage) {
ListView<Integer> lv = new ListView<>();
Button btn = new Button("Run");
btn.setOnAction((ActionEvent event) -> {
JavaFXWorker<Void, Integer> worker = new JavaFXWorker<Void, Integer>() {
@Override
protected Void call() throws Exception {
final int maxCount = 100;
Random random = new Random();
int breakIndex = random.nextInt(maxCount-1)+1;
for (int i = 0; i < breakIndex; i++) {
publish(i);
}
// some break simulating a part long part of the task with no updates
Thread.sleep(3000);
for (int i = breakIndex; i <= maxCount; i++) {
publish(i);
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
lv.getItems().addAll(chunks);
}
};
new Thread(worker).start();
});
Scene scene = new Scene(new VBox(btn, lv));
primaryStage.setScene(scene);
primaryStage.show();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)