我有一个简单的UI窗口,只有一个文本节点,它显示当前时间并绑定到模型:
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中的文本节点不会改变。
我想它只出现过一次。如何使文本节点每次显示curTime的新值时,curTime发生变化?
对不起我的英语:
发布于 2017-11-22 03:05:40
问题是,Clock.curTime只是一个变量,其值会定期更新--它不是一个可观察的属性,因此当它被更改时什么都不会发生。特别是,该变量与Text元素的内容之间没有任何联系。
您所做的就是用这个值初始化一个StringProperty --但是由于属性本身从未更新过,标签也是如此。我认为您想要做的是使curTime成为一个StringProperty,而不仅仅是一个String。现在,每当您更改该属性的值时,Text元素的值就会相应地发生变化。
您应该注意到,与JavaFX/ScalaFX的交互只能发生在JavaFX应用程序线程上,因此如果尝试从另一个线程更新curTime,就会遇到问题。实现这一目标的一种方法是将实际更新curTime的代码传递给Platform.runLater。
然而,一种更简单的方法是使用一个定时的ScalaFX事件来定期更新JavaFX/ScalaFX中的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中
import java.util.Date
import java.text.SimpleDateFormat
import scalafx.animation.PauseTransition
import scalafx.application.Platform
import scalafx.beans.property.StringProperty
import scalafx.util.Duration
import scalafx.Includes._
// Object should be constructed lazily on the JFX App Thread. Verify that...
object Clock {
assert(Platform.isFxApplicationThread)
private val dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss")
val curTime = new StringProperty(getDate())
// Update the curTime property every second, using a timer.
// Note: 1,000 ms = 1 sec
val timer = new PauseTransition(Duration(1000))
timer.onFinished = {_ =>
curTime.value = getDate()
timer.playFromStart() // Wait another second, or you can opt to finish instead.
}
// Start the timer.
timer.play()
private def getDate() = dateFormat.format(new Date())
}https://stackoverflow.com/questions/47413814
复制相似问题