scala - 如何从 Scala 启动 ScalaFX 应用程序?

标签 scala javafx-8 scalafx

我正在尝试从 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.scalaHelloStageDemo.scala 启动并运行得很好,但编译器提示 not found: type HelloStageDemo on 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 的类不是你实现的,而是一个 AppHelper ScalaFX 提供的类。请注意,主要方法首先设置 ACTIVE_APP属性(property) JFXApp的伴随对象:在实践中,什么 AppHelper要做的就是开始 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根据自己的喜好上课,这看起来应该很简单。

关于scala - 如何从 Scala 启动 ScalaFX 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26510469/

相关文章:

scala - 不变性和内存使用

scala - 覆盖助手默认超时

java - 具有长时间运行任务的队列的 Actor 设计

javafx - 更改图表颜色

java - 组合框相同项目选定的操作监听器

JavaFX VBox 调整大小

css - 如何在 ScalaFX 中使用 CSS 设置自定义 TreeCell 的样式?

java - 除了为绑定(bind)添加语法糖之外,ScalaFX 还有哪些好处?

multithreading - 如何从 ScalaFX 线程中获取值?

scala - 无法在 Scala 中编译和运行多个文件