SBT 不会编译 HelloWorld ScalaFX 示例,抱怨类路径中缺少 javafx

SBT won't compile HelloWorld ScalaFX example, complains about javafx missing from the classpath

我是 Scala 的新手,之前从未使用过构建工具,我在编译 scalafx quickstart page 上的 HelloWorld 示例时遇到了一些问题。

我之前尝试在构建路径库选项中使用 scala IDE 4.7.0 Release to run the code, by creating a new scala project, and adding the scalafx.jar version 8.0.102-R11 作为外部 jar。但是,当我右键单击该项目并选择 "Run as" 时,没有选项将其 运行 作为 Scala 应用程序,并且尝试在新的 运行 配置中使用对象名称没有' 似乎工作。我决定尝试将命令行与 SBT 结合使用。

我是运行宁Windows 10,我安装了Java 8,还有JDK 12.0.2。我在我的下载文件夹中创建了一个项目,在一个名为 scalahelloworld 的文件夹中,运行 以下命令:

sbt new scala/hello-world.g8

这正常创建了 hello world 项目,并且编译和 运行s 没有问题。但是,当我尝试按照 scalafx 快速入门指南中的说明进行操作时,添加行

libraryDependencies += "org.scalafx" %% "scalafx" % "8.0.144-R12"

到 build.sbt,以及在我的主要对象中使用他们的示例代码,它给了我一些编译错误:

C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld>sbt
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
[info] Loading project definition from C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\project
[info] Loading settings for project scalahelloworld from build.sbt ...
[info] Set current project to hello-world (in build file:/C:/Users/hugo.barroca/Downloads/SBT%20Project/scalahelloworld/)
[info] sbt server started at local:sbt-server-3c8f646db648b9d2b646
sbt:hello-world> compile
[info] Compiling 1 Scala source to C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\target\scala-2.12\classes ...
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:15:3: Symbol 'type javafx.event.EventTarget' is missing from the classpath.
[error] This symbol is required by 'class scalafx.stage.Window'.
[error] Make sure that type EventTarget is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'Window.class' was compiled against an incompatible version of javafx.event.
[error]   stage = new PrimaryStage {
[error]   ^
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:17:17: Symbol 'term javafx.css' is missing from the classpath.
[error] This symbol is required by 'trait scalafx.css.Styleable'.
[error] Make sure that term css is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'Styleable.class' was compiled against an incompatible version of javafx.
[error]     scene = new Scene {
[error]                 ^
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:17:5: Symbol 'type javafx.scene.Scene' is missing from the classpath.
[error] This symbol is required by 'class scalafx.scene.Scene'.
[error] Make sure that type Scene is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'Scene.class' was compiled against an incompatible version of javafx.scene.
[error]     scene = new Scene {
[error]     ^
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:22:15: Symbol 'type javafx.scene.text.Text' is missing from the classpath.
[error] This symbol is required by 'class scalafx.scene.text.Text'.
[error] Make sure that type Text is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'Text.class' was compiled against an incompatible version of javafx.scene.text.
[error]           new Text {
[error]               ^
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:25:24: Symbol 'term javafx.scene.paint' is missing from the classpath.
[error] This symbol is required by 'class scalafx.scene.paint.LinearGradient'.
[error] Make sure that term paint is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'LinearGradient.class' was compiled against an incompatible version of javafx.scene.
[error]             fill = new LinearGradient(
[error]                        ^
[error] C:\Users\hugo.barroca\Downloads\SBT Project\scalahelloworld\src\main\scala\Main.scala:36:26: Symbol 'type javafx.scene.effect.DropShadow' is missing from the classpath.
[error] This symbol is required by 'class scalafx.scene.effect.DropShadow'.
[error] Make sure that type DropShadow is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'DropShadow.class' was compiled against an incompatible version of javafx.scene.effect.
[error]             effect = new DropShadow {
[error]                          ^
[error] 6 errors found
[error] (Compile / compileIncremental) Compilation failed
sbt:hello-world[error] Total time: 4 s, completed 23/08/2019, 13:19:55
>
sbt:hello-world>

我遇到了一些 SO 页面,这让我相信问题可能出在 either with my version of Java or JDK, or with the classpath. However, I haven't been able to solve it so far. I have tried reinstalling Java, the JDK, STB and tried different versions of the ScalaFX jar, in particular version 8.0.12. I have also tried installing openjfx following this post。到目前为止没有任何变化。

我仅有的代码是示例文件的代码:

package hello

import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.geometry.Insets
import scalafx.scene.Scene
import scalafx.scene.effect.DropShadow
import scalafx.scene.layout.HBox
import scalafx.scene.paint.Color._
import scalafx.scene.paint.{Stops, LinearGradient}
import scalafx.scene.text.Text

object Main extends JFXApp {

  stage = new PrimaryStage {
    title = "ScalaFX Hello World"
    scene = new Scene {
      fill = Black
      content = new HBox {
        padding = Insets(20)
        children = Seq(
          new Text {
            text = "Hello "
            style = "-fx-font-size: 48pt"
            fill = new LinearGradient(
              endX = 0,
              stops = Stops(PaleGreen, SeaGreen))
          },
          new Text {
            text = "World!!!"
            style = "-fx-font-size: 48pt"
            fill = new LinearGradient(
              endX = 0,
              stops = Stops(Cyan, DodgerBlue)
            )
            effect = new DropShadow {
              color = DodgerBlue
              radius = 25
              spread = 0.25
            }
          }
        )
      }
    }
  }
}

我将如何着手解决这个特定问题,以便代码正确编译并显示 HelloWorld scalafx window?

一些挖掘表明您很可能需要为 JavaFX 二进制文件添加一个 OS 特定的依赖项。将以下内容添加到 build.sbt

的底部
lazy val osName = System.getProperty("os.name") match {
  case n if n.startsWith("Linux") => "linux"
  case n if n.startsWith("Mac") => "mac"
  case n if n.startsWith("Windows") => "win"
  case _ => throw new Exception("Unknown platform!")
}

// Add JavaFX dependencies
lazy val javaFXModules = Seq("base", "controls", "fxml", "graphics", "media", "swing", "web")
libraryDependencies ++= javaFXModules.map( m=>
  "org.openjfx" % s"javafx-$m" % "11" classifier osName
)

正如他们在示例项目中所做的那样:https://github.com/scalafx/scalafx-hello-world/blob/master/build.sbt

它也可能是某些 JDK 发行版的问题,例如 Ubuntu 上的 OpenJDK 发行版。如果我没记错的话,有两种不同的方法可以解决它。一种是将 JavaFX 添加到您的依赖项中:

libraryDependencies += "org.openjfx" % "javafx" % "12.0.2" pomOnly()

如果我没记错的话,这可能是最好的方法。如果这项工作通过您的包管理器添加它,在 Ubuntu 中将是:

sudo apt install openjdk-8-jdk openjfx

https://mvnrepository.com/artifact/org.openjfx/javafx and https://askubuntu.com/questions/1091157/javafx-missing-ubuntu-18-04 可能会有用。

此外,正如 askubuntu 指出的那样,您可能希望确保将其设置为 运行,并为您的项目使用 Java 8。