我有一个简单的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改变了?
对不起我的英文:(
答案 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