所以我有一个Controller类,它包含 StringProperty 的 ObservableList 。当我从另一个线程更改任何 StringProperty 对象时,它可以工作。但是,如果我尝试将此 StringProperty 对象绑定到Label,然后从不同的线程更改此对象,则会引发大量错误。 控制器类:
public class Controller implements Initializable{
protected static ObservableList<StringProperty><StringProperty> downloadingsPosition = nFXCollections.observableArrayList();
protected static ObservableList<StringProperty><StringProperty> downloadingsSize = FXCollections.observableArrayList();
private void saveActionEvent() {
...
position.textProperty().bind(positionString);
size.textProperty().bind(sizeString);
}
...
}
流程类:
public class Process implements Runnable {
private FileOutputStream fos;
private int number;
private double totalSize;
public Process(FileOutputStream fos, int number, double totalSize) {
this.fos = fos;
this.number = number;
this.totalSize = totalSize;
}
public void run() {
double size = 0;
String totalSizeStr = String.valueOf("of " + Double.toString(totalSize / 1024.0));
Controller.downloadingsSize.get(number).setValue(totalSizeStr);
try {
while (size < totalSize) {
size = fos.getChannel().size() / (1024.0 * 1024.0);
Controller.downloadingsPosition.get(number).setValue(Double.toString(size));
TimeUnit.MILLISECONDS.sleep(500);
System.out.println(size);
}
}
catch (Exception e) {
}
}
}
这些是错误:
Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:438)
at javafx.scene.Parent$2.onProposedChange(Parent.java:364)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$$Lambda$96/698755630.call(Unknown Source)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.access$000(StringPropertyBase.java:49)
at javafx.beans.property.StringPropertyBase$Listener.invalidated(StringPropertyBase.java:230)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at sample.Process.run(Process.java:30)
at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:0)
您需要阅读这篇文章:https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
总结的问题是JavaFX期望UI的任何更改都发生在运行应用程序的主线程上。如果您需要从另一个线程进行更改,您应该使用消息队列与主线程进行通信。
或者,如本文所述,您可以使用JavaFX提供的一种结构来跨线程进行更改。