如何从ScalaFX线程获取值?

时间:2014-03-24 01:21:54

标签: multithreading scala javafx-2 future scalafx

我有一个myNode: scalafx.scene.Node,我想将其转换为位图,以便将其保存到磁盘,将其与其他位图进行比较等等。我认为正确的代码可以将其转换为{{ 1}}是

scalafx.scene.image.WritableImage

然后我应该可以将其转换为val writableImg = new Scene { root = new Group(myNode) }.snapshot(null)

java.awt.image.RenderedImage

问题,正如您可能已经意识到的那样,我必须运行代码才能在ScalaFX线程上获取val renderedImg = SwingFXUtils.fromFXImage(writableImg, null) 。有一个问题here解释了如何返回一个值,但我没有任何运气将其转换为Scala。我试过这个:

wrImg

但代码只是挂起而永远不会完成。任何人都可以提供惯用的Scala版本和/或告诉我为什么代码永远不会返回?

1 个答案:

答案 0 :(得分:1)

如果您只想将图像保存到磁盘,只需在同一个线程上执行即可避免复杂化传递图像。这样的事情会起作用:

Platform.runLater {
  val node = new Circle {
    centerX = 200
    centerY = 200
    radius = 50
    stroke = Color.BROWN
    strokeWidth = 2
    fill = Color.DARKKHAKI
  }
  val jfxImage = node.snapshot(new SnapshotParameters(), null)
  val bufferedImage = SwingFXUtils.fromFXImage(jfxImage, null)
  val file = new File("./snapshot.png")
  println("Writing snapshot to: " + file.getAbsolutePath)
  javax.imageio.ImageIO.write(bufferedImage, "png", file)
  ()
}

()让闭包返回Unit,因此ScalaFX Platform.runLater很高兴。

<强>更新

如果您希望获得Platform.runLater的值,您在问题中建议的方法一般应该没问题。但是,您要确保不阻止FX应用程序线程。如果你在FX应用程序线程上调用Platform.runLater,你将会锁定,所以你可能想要这样的东西

def makeSnapshot() = myNode.snapshot(new SnapshotParameters(), null)

val writableImg = if (Platform.isFxApplicationThread) {
  makeSnapshot()
} else {
  val futureTask = new FutureTask(new Callable[WritableImage]() {
    override def call(): WritableImage = makeSnapshot()
  })
  Platform.runLater(futureTask)
  futureTask.get()
}