我正在尝试使用以下代码从http://www.scalafx.org启动ScalaFX Hello World应用程序:
package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
javafx.application.Application.launch(classOf[HelloStageDemo], args: _*)
}
为了澄清,我在
car.cadr
包中有两个Scala文件:ApplicationStarter.scala
和HelloStageDemo.scala
。HelloStageDemo.scala
启动并运行得非常好,但是编译器抱怨not found: type HelloStageDemo
上的ApplicationStarter.scala
。即使我使用import car.cadr.HelloStageDemo
手动导入它,编译器仍然会抱怨。我正在使用Scala 2.11.1和ScalaFx 8.0.20-R6。
最佳答案
您在这里遇到几个问题。
让我们从编译器告诉您的内容开始:not found: type HelloStageDemo
。这是有道理的,因为HelloStageDemo示例定义了一个object
而不是一个类:因此,scalac编译器实际上输出了一个名为HelloStageDemo$
的类(因为您还可以定义一个class HelloStageDemo
,并且都需要使用不同的名称进行编译)。
接下来,如果将object HelloStageDemo
更改为class HelloStageDemo
,则会出现以下错误:
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)
这是因为
launch
方法仅存在以下签名(此处为Java):public static void launch(Class<? extends javafx.application.Application> appClass, String... args)
public static void launch(String... args)
但是
HelloStageDemo
既不是String
也不是javafx.application.Application
的一种,因此这不起作用。这是因为ScalaFX的
JFXApp
特性的工作方式。这是您以通常方式启动ScalaFX应用程序时执行的主要方法(即,主要类是扩展的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...
}
因此,在ScalaFX中,扩展
javafx.application.Application
的类不是您实现的类,而是ScalaFX提供的AppHelper
类。注意,main方法首先在ACTIVE_APP
的伴随对象上设置JFXApp
属性:实际上,AppHelper
将要做的是start JFXApp.ACTIVE_APP
。这是代码: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()
}
}
总之,如果您要启动
HelloStageDemo
,但由于某种原因,您不希望HelloStageDemo
成为主类,则最简单的解决方案是仅调用main方法-毕竟,它只是一种与其他方法相同的方法:package car.cadr
object ApplicationStarter {
def main(args: Array[String]) =
HelloStageDemo.main(Array())
}
但是,如果由于某种原因,您绝对必须通过
javafx.application.Application.launch
方法启动ScalaFX应用程序,那么我认为最好的解决方案是根据自己的喜好重新实现AppHelper
类,这看起来应该非常简单。