I am trying to understand the message passing possibilities of ScalaFX in combination with ScalaFXML. I created a small example, which has two views with controllers defined in the FXML. The first (or Main
) view, is supposed to send a String to the second (or Dialog
) view, by a button press.
I followed the example of the ScalaFXML Github page and used a trait in order to get the controller and it's possible for me to call a method on the Dialog controller, which sets a field to different value. This method gets called correctly, but the field isn't overwritten, when I check by clicking a button. Does this have something to do with ScalaFXML injecting the Controller?
Bellow I have the code for the two controllers
@sfxml
class MainController(val clicky: Button,
val inputText: TextField,
val resultText: TextArea) {
/** Creates a new window (in addition to the main window) and passes the contents of the text view to this window */
def onButtonPressed(): Unit = {
// Create the new window
val dialogFXML: String = "/Dialog.fxml"
val resource = getClass.getResource(dialogFXML)
val rootView = FXMLView(resource, NoDependencyResolver)
val loader = new FXMLLoader(resource, NoDependencyResolver)
loader.load()
val controller = loader.getController[AmountReceiver]
controller.setAmount(inputText.text.value)
val dialog = new Stage() {
title = "Add Person"
scene = new Scene(rootView)
resizable = false
initModality(Modality.ApplicationModal)
}
if (!dialog.showing()) {
dialog.show()
} else {
dialog.requestFocus()
}
}
}
and
@sfxml
class DialogController(val minAmountOfWords: Label,
val sendToMainButton: Button,
val input: TextArea) extends AmountReceiver {
var amount: String = "empty"
def submitText(): Unit = {
println(s"The actual amount is ${this.amount}")
// Close Dialog
quitDialog()
}
override def setAmount(amount: String): Unit = {
this.amount = amount
println(s"Setting the amount to ${this.amount}")
}
def quitDialog(): Unit = {
val stage: Stage = input.getScene.getWindow.asInstanceOf[Stage]
stage.close()
}
}
Running this code and entering "2" in the textfield, will print the following output:
Setting the amount to 2
The actual amount is empty
I actually figured it out myself. The problem lays within the rootView
, which is received by creating a new FXMLView
. In order access the correct controller, the rootView
has to be received by the loader, which is already used to get the controller.
So calling
val rootView = loader.getRoot[jfxs.Parent]
instead of
val rootView = FXMLView(resource, NoDependencyResolver)
Like in the above example, the rootView
is passed to the Scene constructor.