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.