简体   繁体   English

ScalaFX如何创建对var(ObjectProperty)中的更改做出反应的方法?

[英]ScalaFX How do I create a method to react to changes in a var (ObjectProperty)?

I am making a multiplayer game client with ScalaFX GUI and Akka remoting for networking. 我正在使用ScalaFX GUI和Akka远程处理网络制作多人游戏客户端。 When my client receives game data it stores it inside Model.gameData. 当我的客户收到游戏数据时,它将其存储在Model.gameData中。 I need my GUI to respond to this variable change. 我需要我的GUI来响应此变量更改。

I used gameData to create data:ObjectProperty in my Model object: 我使用gameData在我的Model对象中创建data:ObjectProperty:

object Model  {
    var gameData:Option[GameData] = None
    val data = new ObjectProperty(this,"data",Model.gameData)
    ...
}

drawGrid and drawPlayer are methods I use to update the GUI, located in CleintGUI object. drawGrid和drawPlayer是我用来更新GUI的方法,位于CleintGUI对象中。 I tired using addListener and onChange, they compile but the methods I placed inside of them are never invoked. 我厌倦了使用addListener和onChange进行编译,但它们始终被编译,但从未调用我放置在其中的方法。

object ClientGUI extends JFXApp{
 ...

 Model.data.addListener{ (o: javafx.beans.value.ObservableValue[_ <:Option[GameData]], oldVal: Option[GameData], newVal: Option[GameData]) =>
  drawGrid
  drawPlayer
 }

 Model.data onChange {
  drawGrid
  drawPlayer
 }

}

What am I missing? 我想念什么? Am I declaring data:ObectProperty or methods inside my ClientGUI incorrectly? 我在ClientGUI中错误地声明了data:ObectProperty或方法吗?

drawGrid and drawPlayer both work when I call them manually by creating an event through submitting a string in a TextField. 当我通过在TextField中提交字符串创建事件来手动调用它们时,drawGrid和drawPlayer都可以工作。 When I receive GameData I also tried to directly call drawGrid and drawPlayer form inside of my actor class, but I got an error "Not an FX thread". 当我收到GameData时,我还尝试直接在actor类内部调用drawGrid和drawPlayer表单,但出现错误“ Not a FX thread”。

Edit: I got the GUI to update by mutating control attributes. 编辑:我得到了通过更改控件属性来更新GUI。 However, ideally I would want to define the control attributes by using conditional expressions: 但是,理想情况下,我想使用条件表达式来定义控件属性:

val data = new BooleanProperty(this,"data",Model.gameData.isDefined)

val msgLabel = new Label{
                 text <== when(data) choose " " otherwise "No GameData"
               } 

But this doesn't work as I can't figure out a way to define BooleanProperty such that when(data) changes value depending on boolean Model.gameData.isDefined 但这是行不通的,因为我无法找出一种定义BooleanProperty的方式,以便when(data)根据boolean Model.gameData.isDefined来更改值

I was adding new elements to the GUI when I received gameData, by using GridPane.add method. 当我使用GridPane.add方法接收到gameData时,正在向GUI添加新元素。

Instead of doing that I added all the controls(gui nodes/elements) during object creation and then changed their relevant attributes when I receive gameData. 我没有这样做,而是在对象创建过程中添加了所有控件(gui节点/元素),然后在收到gameData时更改了它们的相关属性。

eg I set Label.text from "No Game Data" to an empty string when I receive gameData: 例如,当我收到gameData时,我将Label.text从“ No Game Data”设置为一个空字符串:

def update {
ClientGUI.msgLabel = " "
}

I don't think this is the best approach as now I have publicly available vars in a multi threaded application, but since I only change them from one place when I receive new data it should be fine. 我不认为这是最好的方法,因为现在我在多线程应用程序中具有公开可用的var,但是由于我只在收到新数据时才从一个位置更改它们,所以应该没问题。

Ideally I would want to define the control attributes by using conditional expressions: 理想情况下,我想使用条件表达式来定义控件属性:

val data = new BooleanProperty(this,"data",Model.gameData.isDefined)

val msgLabel = new Label{
                 text <== when(data) choose " " otherwise "No GameData"
               } 

But this doesn't work as I can't figure out a way to define BooleanProperty such that when(data) changes value depending on boolean Model.gameData.isDefined 但这是行不通的,因为我无法找出一种定义BooleanProperty的方式,以便when(data)根据boolean Model.gameData.isDefined来更改值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM