ScalaFX。实时绑定

时间:2017-11-21 13:03:23

标签: scala user-interface binding scalafx

我有一个简单的UI窗口,只有一个Text节点,显示当前时间并绑定到模型:

import model.Clock

import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.StringProperty
import scalafx.geometry.Insets
import scalafx.scene.Scene
import scalafx.scene.layout.HBox
import scalafx.scene.text.Text
import scalafx.Includes._

object Main extends JFXApp {
    val clock = new Text()
    clock.textProperty().bind( new StringProperty(Clock.curTime) )

    stage = new PrimaryStage {
        onShowing = handle { Clock.startClock }
        title = "ScalaFX clock"
        scene = new Scene {
            content = new HBox {
                padding = Insets(50, 80, 50, 80)
                children = clock
            }
        }
    }
}

一个模特:

import java.util.Date
import java.text.SimpleDateFormat

object Clock {
    var curTime = ""
    private lazy val dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss")

    def startClock = {
        /*A code, witch runs in another Thread and 
          changes curTime every 1 second skipped here.
          Only one change of curTime for simplicity.
        */

        curTime = dateFormat format new Date
    }
}

我的问题是:当curTime变量发生变化时,UI中的文本节点不会改变。

我猜它会在stratup上渲染一次。如何使文本节点每次都显示curTime的新值,curTime改变了?

对不起我的英文:(

1 个答案:

答案 0 :(得分:2)

问题是Clock.curTime只是一个变量,其值会定期更新 - 它不是观察到的属性,所以当它被更改时没有任何反应。特别是,该变量与您的Text元素内容之间没有任何关联

您所做的是使用该值初始化StringProperty - 但由于属性本身永远不会更新,因此标签也不会更新。我认为你想要做的是让curTime成为StringProperty而不仅仅是String。现在,每当您更改该属性的值时,Text元素的值都会相应更改。

您应该注意与 JavaFX / ScalaFX 的交互只能在 JavaFX应用程序线程上进行,因此如果您尝试更新{{1从另一个线程来看,你会遇到问题。实现这一目标的一种方法是将实际更新curTime的代码传递给curTime

但是,更简单的方法是使用定时的 ScalaFX 事件定期从 JavaFX / ScalaFX 中更新Platform.runLater,如下:

curTime

import model.Clock import scalafx.application.JFXApp import scalafx.application.JFXApp.PrimaryStage import scalafx.geometry.Insets import scalafx.scene.Scene import scalafx.scene.layout.HBox import scalafx.scene.text.Text import scalafx.Includes._ object Main extends JFXApp { val clock = new Text() // Clock.curTime is now a StringProperty, which we bind to clock's text. Since clock is // created lazily, it starts the timer event, so we do not need startClock either. clock.text <== Clock.curTime // Create the stage & scene. stage = new PrimaryStage { title = "ScalaFX clock" scene = new Scene { content = new HBox { padding = Insets(50, 80, 50, 80) children = clock } } } }

Clock.scala