3

I am trying to use create a scala program that uses the FXML file generated from JavaFX SceneBuilder for the GUI. Although https://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm is java, I am using it as my example starting point. (Couldn't find anything better.)

I am able to get this example to run if I use the java version of the controller class, as shown in the example. (Works with either the java version or a scala version of the class that extends Application and has the overridden start method in it.) But if I replace this java version controller class with a scala version, I get the error below:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)

Here is what Intellij converted the java version controller (which I call jController) to a scala version (which I call sController) when I used the menu item Code/Convert Java to Scala:

import javafx.event.ActionEvent
import javafx.fxml.FXML
import javafx.scene.text._

class sController {
  @FXML private val actiontarget: Text = null

  @FXML protected def handleSubmitButtonAction(event: ActionEvent): Unit = {
    actiontarget.setText("Sign in button pressed")
  }
}

Of course I also changed <GridPane fx:controller="jController" to <GridPane fx:controller="sController" in the generated FXML file.

I've also tried modifications to the scala version of the controller, starting from the code above that Intellij generated, but nothing worked.

If I replace

@FXML private val actiontarget: Text = null

with

@FXML private val actiontarget: Text = new Text()

then it runs without the exception but does not respond to the button being pressed.

I also tried the javascript version, shown in the example, in place of the controller version, but I don't know anything about javascript and Intellij does not seem to have the "JavaScript and TypeScript bundled plugin" available anymore as referred to here: https://www.jetbrains.com/help/idea/2020.3/javascript-specific-guidelines.html#ws_JavaScript_before_you_start I tried different javascript and typescript plugins, but didn't help.

Any ideas, or is this article correct? https://bugs.openjdk.java.net/browse/JDK-8116127

LarryK
  • 27
  • 4
  • Where did you learn `@FXML private val actiontarget: Text = null`? – SedJ601 Jan 01 '21 at 22:56
  • Have you tried `@FXML private val actiontarget;`? – SedJ601 Jan 01 '21 at 22:56
  • 1
    Post the complete stack trace (format it as code), as well as the FXML file – James_D Jan 01 '21 at 23:06
  • The "= null" was from what Intellij generated when I used the menu item Code/Convert Java to Scala (which I believe is from the Scalagen, Java to Scala Converter plugin. – LarryK Jan 01 '21 at 23:10
  • When I "...actiontarget;" I get the compile error: '=' expected but ';' found. – LarryK Jan 01 '21 at 23:13
  • You should be using this format: `private val fx:id: NodeType`. See [here](https://vigoo.github.io/posts/2014-01-12-scalafx-with-fxml.html) for an example. Your `Controller` class looks very different than the linked example. – SedJ601 Jan 02 '21 at 03:08
  • 2
    Sedrick, Thanks for the link to the example. Unfortunately it uses ScalaFX and a small library that the author wrote called ScalaFXML. I just want to use JavaFX SceneBuilder for the GUI, and no ScalaFX. I believe this is the most modern/mature GUI framework for the JVM, aside from pure JavaFX. So, since other approaches do not look straight-forward, clean, and mature, I guess I will go with: SceneBuilder to generate FXML for the GUI, java for the Controller, and scala for everything else. – LarryK Jan 02 '21 at 05:43
  • Sorry @LarryK. I did not notice that. – SedJ601 Jan 02 '21 at 23:11

1 Answers1

1

I managed to get this running as follows:

import javafx.event.ActionEvent
import javafx.fxml.FXML
import javafx.scene.text._

class sController {
  @FXML private var actiontarget: Text = _

  @FXML protected def handleSubmitButtonAction(event: ActionEvent): Unit = {
    actiontarget.setText("Sign in button pressed")
  }
}

i.e. use a var field.

I left the field private and still initialized it to _ or null. This is basically as described in programmersdigest.de. But, note that I am not very far with my own application, yet. It could be that the field additionally has to be made public because otherwise the compiler is forced to do name mangling and messes things up. See here for more details.

vinjana
  • 61
  • 2