2014-11-28 2 views
0

У меня есть ImageView в моем представлении и пытаюсь отобразить с ним экземпляр WritableImage. Я рисую его в потоке outper и передаю его в представление, прослушивая событие изменения ObjectProperty.JavaFX ImageView throwing IllegalStateException

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

Кто-нибудь может это объяснить?

ответ

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 Application Thread.

+0

Отличный ответ Приветствия. Я очень новичок в java8, поэтому использовал стиль, который мне знаком;) на данный момент я не уверен, как заставить этот код работать в моей. Но я попробую как можно скорее и пометю вам ответ – Nemo

+0

Версия Platform.runLater (...) работала для меня, приветствует приятеля – Nemo

Смежные вопросы