I'm trying to launch the ScalaFX Hello World application from http://www.scalafx.org with the following code:
package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
javafx.application.Application.launch(classOf[HelloStageDemo], args: _*)
}
To clarify, I have two Scala files in the car.cadr package: ApplicationStarter.scala and HelloStageDemo.scala.
HelloStageDemo.scala starts and runs perfectly fine, but the compiler is complaining about not found: type HelloStageDemo on ApplicationStarter.scala. Even if I manually import it with import car.cadr.HelloStageDemo the compiler still complains.
I'm using Scala 2.11.1 and ScalaFx 8.0.20-R6.
You have several problems here.
Let's start with the one the compiler is telling you about: not found: type HelloStageDemo. This makes sense because the HelloStageDemo example defines an object and not a class: so the scalac compiler actually outputs a class named HelloStageDemo$ (because you could also define a class HelloStageDemo, and both need to be compiled with different names).
Next, if you change your object HelloStageDemo for a class HelloStageDemo, you will get the following error:
Error:(7, 36) overloaded method value launch with alternatives:
(x$1: String*)Unit <and>
(x$1: Class[_ <: javafx.application.Application],x$2: String*)Unit
cannot be applied to (Class[car.cadr.HelloStageDemo], String)
This is because the launch method exists only with the following signatures (here in Java):
public static void launch(Class<? extends javafx.application.Application> appClass, String... args)public static void launch(String... args)But HelloStageDemo is neither a String nor a kind of javafx.application.Application, so this cannot work.
This is because of the way ScalaFX's JFXApp trait works. Here's the main metrhod that gets executed when you launch a ScalaFX application the usual way (ie., the main class is the one extending JFXApp):
import javafx.{application => jfxa}
trait JFXApp extends DelayedInit {
// ...code removed for clarity...
def main(args: Array[String]) {
JFXApp.ACTIVE_APP = this
arguments = args
// Put any further non-essential initialization here.
/* Launch the JFX application.
*/
jfxa.Application.launch(classOf[AppHelper], args: _*)
}
// ...code removed for clarity...
}
So, in ScalaFX, the class extending javafx.application.Application isn't the one you implement, but a AppHelper class provided by ScalaFX. Notice that the main method first sets the ACTIVE_APP property on JFXApp's companion object: in practice, what AppHelper will do is start JFXApp.ACTIVE_APP. Here is the code:
package scalafx.application
private[application] class AppHelper extends javafx.application.Application {
def start(stage: javafx.stage.Stage) {
JFXApp.STAGE = stage
JFXApp.ACTIVE_APP.init()
if (JFXApp.AUTO_SHOW) {
JFXApp.STAGE.show()
}
}
override def stop() {
JFXApp.ACTIVE_APP.stopApp()
}
}
In conclusion, if you want to launch HelloStageDemo but, for some reason, you don't want HelloStageDemo to be the main class, the simplest solution would be to just call the main method - after all, it's just a method like any other:
package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
HelloStageDemo.main(Array())
}
But if, for some reason, you absolutely had to launch your ScalaFX application trough the javafx.application.Application.launch method, I think the best solution would be to re-implement the AppHelper class to your liking, which seems like it should be pretty simple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With