我在视图中有一个ImageView,并尝试用它显示WritableImage实例。我在一个外部线程中绘制它并通过监听ObjectProperty的更改事件将其传递给视图。
public void changed(ObservableValue<? extends Image> observable,
Image oldValue, Image newValue) {
this.imageView.setImage(newValue);
}
imageView应该准备好接收图像,它由我的mainView显示。但它正在从
中引发IllegalStateException线程“Thread-4”中的异常java.lang.IllegalStateException:不在FX应用程序线程上; currentThread = Thread-4
有人能解释一下吗?
答案 0 :(得分:4)
该异常基本上告诉您问题所在:您正在从FX应用程序线程以外的线程更改场景图的一部分状态。原因是在更改属性的同一线程上调用了侦听器方法。
您有几种方法可以解决此问题:一种方法是使用Platform.runLater(...)
。您可以在侦听器中执行此操作:
public void changed(ObservableValue<? extends Image> observable,
Image oldValue, Image newValue) {
Platform.runLater(new Runnable() {
@Override
public void run() {
this.imageView.setImage(newValue);
}
});
}
或者您也可以在FX Application Thread上设置属性的值。
您还没有显示太多代码,但您也可以使用Task
来计算图片。所以不是像:
new Thread(new Runnable() {
@Override
public void run() {
WritableImage image = new WritableImage(...);
/// draw on image....
myImageProperty.set(image);
}
});
你可以做点什么
Task<Image> imageTask = new Task<Image>() {
@Override
public Image call() {
WritableImage image = new WritableImage(...);
// draw on image....
return image ;
}
});
imageTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
myImageProperty.set(imageTask.getValue());
}
});
new Thread(imageTask).start();
(这在Java 8中更清晰;我在问题中使用了这种风格时发布了Java 7兼容代码。)
这里你避免使用低级API(Platform.runLater()
),而是使用setOnSucceeded
中的一种回调方法(Task
),保证在FX应用程序上调用线程。