4

myNode: scalafx.scene.Nodeディスクに保存したり、他のビットマップと比較したりできるように、ビットマップに変換したい があります。それを に変換する正しいコードscalafx.scene.image.WritableImage

val writableImg = new Scene { root = new Group(myNode) }.snapshot(null)

java.awt.image.RenderedImageそして、それをwithに変えることができるはずです

val renderedImg = SwingFXUtils.fromFXImage(writableImg, null)

問題は、お気づきかもしれませんが、コードを実行wrImgして ScalaFX スレッドにアクセスする必要があることです。値を返す方法を説明する質問がここにありますが、それを Scala に変換する運がありません。私はこれを試しました:

lazy val writableImg: WritableImage = {
  val wrImg = new FutureTask(new Callable[WritableImage]() {
    override def call(): WritableImage = {
      new Scene { root = new Group(myNode) }.snapshot(null)
    }
  })
  Platform.runLater(wrImg)
  wrImg.get()
}

しかし、コードはハングするだけで完了しません。誰でも慣用的な Scala バージョンを提供したり、コードが返されない理由を教えてもらえますか?

4

1 に答える 1

2

画像をディスクに保存したいだけの場合は、同じスレッドで簡単に実行でき、画像を渡す複雑さを回避できます。次のようなものが機能します。

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 を返すクロージャを持っているので、ScalaFXPlatform.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()
}
于 2014-03-25T00:36:34.813 に答える