簡體   English   中英

如何從Scala中創建ScalaFX應用程序?

[英]How do Iaunch a ScalaFX application from Scala?

我正在嘗試使用以下代碼從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 HelloStageDemoApplicationStarter.scalanot found: type HelloStageDemo 即使我用import car.cadr.HelloStageDemo手動導入它,編譯器仍然會抱怨。

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

你有幾個問題。

讓我們從編譯器告訴你的那個開始: not found: type HelloStageDemo 這是有道理的,因為HelloStageDemo示例定義了一個object而不是一個類:因此scalac編譯器實際上輸出了一個名為HelloStageDemo$的類(因為您還可以定義一個class 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提供的AppHelper類。 請注意,main方法首先在JFXApp的伴隨對象上設置ACTIVE_APP屬性:實際上, 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類,這似乎應該是很簡單。

這是一個用於啟動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
   } 
}

非ScalaFX解決方案:

我知道這個問題已經回答了。 但是如果你想使用javafx.application.Application來啟動。 只需為類和對象設置不同的名稱,結果是沒有“MyClass $ .class”和“MyClass.class”,其中第二個不是Applications Child而是對象。

以一種巧妙的方式解決了我的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM