3

我正在尝试使用以下代码从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.scalaHelloStageDemo.scala. HelloStageDemo.scala启动并运行得很好,但编译器抱怨not found: type HelloStageDemoon ApplicationStarter.scala. 即使我用import car.cadr.HelloStageDemo编译器手动导入它仍然会抱怨。

我正在使用 Scala 2.11.1 和 ScalaFx 8.0.20-R6。

4

3 回答 3

2

你在这里有几个问题。

让我们从编译器告诉你的那个开始:not found: type HelloStageDemo. 这是有道理的,因为 HelloStageDemo 示例定义了 anobject而不是类:因此 scalac 编译器实际上输出了一个名为的类HelloStageDemo$(因为您也可以定义 a class HelloStageDemo,并且两者都需要使用不同的名称进行编译)。


接下来,如果您更改您的object HelloStageDemofor a 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既不是 aString也不是 kind of javafx.application.Application,所以这行不通。


这是因为 ScalaFX 的JFXApptrait 工作方式。这是当您以通常的方式启动 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不是您实现的类,而是AppHelperScalaFX 提供的类。请注意, 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())
}

但是,如果由于某种原因,您绝对必须通过该方法启动您的 ScalaFX 应用程序javafx.application.Application.launch,我认为最好的解决方案是根据您的喜好重新实现AppHelper该类,这看起来应该很简单。

于 2014-10-22T19:23:35.297 回答
0

这是一个用于启动 ScalaFX 应用程序的简单模板。

object MyApp {
   def main(args: Array[String]) {
        MyApp.launch(classOf[MyApp], args: _*)
    }
}

class MyApp extends JFXApp {

   override def start(primaryStage: Stage): Unit = {
      // initialization here
   } 
}
于 2014-10-22T19:04:12.413 回答
0

非 ScalaFX 解决方案:

我知道这个问题已经得到解答并且已经过时了。但是如果你想使用javafx.application.Application,来启动。只需为类和对象设置不同的名称,结果就没有“MyClass$.class”和“MyClass.class”,其中第二个不是应用程序子对象而是对象。

巧妙地解决了我的问题。

于 2018-02-06T07:19:20.073 回答