0

I have a ScalaFX application and I am using FXML for my views. I am having a terrible time connecting the views to the controllers. I cannot find much information online except examples on Github and it doesn't work even when I try to mimic how they did it. Here is how I connect it in the FXML.

imports...

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="520.0" minWidth="880.0" prefHeight="520.0"
            prefWidth="880.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="scala/scalafxml/ToolbarController">
<center....

Here is my controller class...

@sfxml
class ToolbarController extends JFXApp {
  //open new form
   def newForm = {
    val resource = getClass.getResource("/scala/scalafxml/form.fxml")

The stack trace says it specifically can't find the controller class referenced by fx:controller. Here it is.

Exception in Application start method
Workaround until RT-13281 is implemented: keep toolkit alive
[error] (run-main-0) java.lang.RuntimeException: Exception in Application start method
java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(LauncherImpl.java:182)
    at com.sun.javafx.application.LauncherImpl$$Lambda$9/777613804.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
/Users/patrickslagle/scala/MyApps/PattyCakesWorksheet/target/scala-2.10/classes/scalafxml/calendar.fxml:9

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
    at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:104)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:918)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:967)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:216)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:740)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2711)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2531)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3218)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3128)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3108)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3101)
    at FXMLMain$delayedInit$body.apply(FXMLMain.scala:16)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scalafx.application.JFXApp$$anonfun$init$1.apply(JFXApp.scala:297)
    at scalafx.application.JFXApp$$anonfun$init$1.apply(JFXApp.scala:297)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
    at scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:45)
    at scalafx.application.JFXApp$class.init(JFXApp.scala:297)
    at FXMLMain$.init(FXMLMain.scala:10)
    at scalafx.application.AppHelper.start(AppHelper.scala:33)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(LauncherImpl.java:863)
    at com.sun.javafx.application.LauncherImpl$$Lambda$60/206252937.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl$$Lambda$56/1146564181.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
    at com.sun.javafx.application.PlatformImpl$$Lambda$58/354390534.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
    at com.sun.javafx.application.PlatformImpl$$Lambda$57/1198063642.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Caused by: java.lang.ClassNotFoundException: scala/scalafxml/ToolbarController
    at java.lang.ClassLoader.findClass(ClassLoader.java:530)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) Nonzero exit code: 1
[error] Total time: 11 s, completed May 24, 2016 3:32:56 PM

The FXML file is found at src/main/resources/scalafxml/calendar.fxml and the controller is in src/main/scala/scalafxml/ToolbarController.scala.

I may have something obviously wrong as I'm pretty green at Scala. Any pointers are greatly appreciated.

Patrick S.
  • 275
  • 1
  • 5
  • 19
  • 1
    I don't know much about Scala, but the package reference for the `fx:controller` should be a valid class specification (e.g. you should use `.` instead of `/` when specifying the fully qualified path of the class). I don't know what package your controller is in, but I'll assume it is a package named `scalafxml`, so the fully qualified reference to it would be `scalafxml.ToolbarController`. I doubt it would be `scala.scalafxml.ToolbarController` as would expect the `scala` package to be reserved for the `scala` system libraries, not user application code. – jewelsea May 24 '16 at 19:45
  • 2
    Also, it is unlikely you really want: `ToolbarController extends JFXApp`, as normally controllers should not extend applications, or weird an confusing things can happen due to the application instance being created by the JavaFX launcher and another controller instance being created by the FMXLLoader. – jewelsea May 24 '16 at 19:47
  • 2
    My advice is to code your JavaFX application in Java until you are familiar with JavaFX and how it works, then, if you wish, switch over to Scala at a latter time after you have also learnt more about how that works. I.e., make sure you are familiar with one or the other and don't try to learn both JavaFX and Scala at the same time, just my unsolicited opinion. – jewelsea May 24 '16 at 19:50
  • Can you post complete example of what you are doing, as explained here https://stackoverflow.com/help/mcve – Jarek May 26 '16 at 11:13
  • Thank you all for your help and advice. I was able to solve the problem in this way: I changed the path in fx:controller to use the '.' instead of '/'. I also got rid of the scalafxml directory and just used a "scala" directory in resources. For some reason, when I had the scala/scalafxml/ format it was not finding my controller. After doing those two things, my application is working as expected by just referencing it as "fx:controller='scala.ToolbarController'". – Patrick S. May 26 '16 at 17:54

1 Answers1

2

Take a look at this standalone example: https://github.com/vigoo/scalafxml-unit-converter-example

You should have a separate controller class and a JFXApp, and use theFXMLView constructor from ScalaFXML to create the view.

vigoo
  • 301
  • 4
  • 12