首页 > 解决方案 > scalafx 自定义绑定竞争条件

问题描述

我正在尝试使用 Amazon Rekognition 在图像中检测到的文本周围绘制框。

这是一个精简的 JavaFX 应用程序,它应该可以做到这一点:

object TextRekognizeGui extends JFXApp {
  lazy val rekognition: Option[AmazonRekognition] =
    RekogClient.get(config.AwsConfig.rekogEndpoint, config.AwsConfig.region)
  private val config = MainConfig.loadConfig()

  stage = new PrimaryStage {
    scene = new Scene {
      var imgFile: Option[File] = None

      content = new HBox {
        val imgFile: ObjectProperty[Option[File]] = ObjectProperty(None)
        val img: ObjectProperty[Option[Image]] = ObjectProperty(None)
        val lines: ObjectProperty[Seq[TextDetection]] = ObjectProperty(Seq.empty)
        // These two print statements are always executed when we press the appropriate button.
        img.onChange((_, _, newValue) => println("New image"))
        lines.onChange((_, _, newValue) => println(s"${newValue.length} new text detections"))
        children = Seq(
          new VBox {
            children = Seq(
              new OpenButton(img, imgFile, lines, stage),
              new RekogButton(img, imgFile, lines, rekognition)
            )
          },
          new ResultPane(675, 425, img, lines))
      }
    }
  }

  stage.show
}

class ResultPane(width: Double, height: Double, img: ObjectProperty[Option[Image]],
                 textDetections: ObjectProperty[Seq[TextDetection]]) extends AnchorPane { private val emptyPane: Node = Rectangle(0, 0, width, height)

  // This print statement, and the one below, are often not executed even when their dependencies change.
  private val backdrop = Bindings.createObjectBinding[Node](
    () => {println("new backdrop"); img.value.map(new MainImageView(_)).getOrElse(emptyPane)},
    img
  )

  private val outlines = Bindings.createObjectBinding[Seq[Node]](
    () => {println("new outlines"); textDetections.value map getTextOutline},
    textDetections
  )

这在我看来好像我遵循了 ScalaFX 文档的说明创建自定义绑定。当我单击“RekogButton”时,我希望看到“新文本检测”消息以及“新轮廓”消息,但通常我只看到“新文本检测”消息。

该行为在程序的整个生命周期中似乎都是相同的,但它仅在某些运行时表现出来。img->绑定也会出现同样的问题background,但出现的频率较低。

为什么我的属性在更改时有时无法调用绑定?

编辑 1 JavaFX 将与绑定关联的侦听器存储为弱引用,这意味着它们仍然可以被垃圾收集,除非另一个对象拥有对它们的强引用或软引用。因此,如果垃圾收集器恰好在应用程序初始化和绘制轮廓之间运行,我的应用程序似乎会失败。

这很奇怪,因为我似乎对绑定有很强的引用——结果窗格中值“outlines”的“delegate”字段。更深入地研究它。

标签: scalajavafxscalafx

解决方案


推荐阅读