JavaFX ImageView抛出IllegalStateException

时间:2014-11-28 14:27:16

标签: java exception javafx

我在视图中有一个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

有人能解释一下吗?

1 个答案:

答案 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应用程序上调用线程。