Dimitry
Dimitry

Reputation: 41

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. When my client receives game data it stores it inside Model.gameData. I need my GUI to respond to this variable change.

I used gameData to create data:ObjectProperty in my Model object:

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. I tired using addListener and onChange, they compile but the methods I placed inside of them are never invoked.

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?

drawGrid and drawPlayer both work when I call them manually by creating an event through submitting a string in a TextField. 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".

Edit: I got the GUI to update by mutating control attributes. 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

Upvotes: 3

Views: 527

Answers (1)

Dimitry
Dimitry

Reputation: 41

I was adding new elements to the GUI when I received gameData, by using GridPane.add method.

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.

e.g. I set Label.text from "No Game Data" to an empty string when I receive gameData:

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.

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

Upvotes: 1

Related Questions