Okay, so let’s remove ScalaFX from the equation. I’ve hacked some ideas together and arrived at a working solution. Setup is the same as it was, i.e OpenJDK 11, OpenJFX 14, Ubuntu and SBT.
In directory /tmp/javafx-in-scala
I’ve created two files:
build.sbt:
name := "javafx-in-scala"
version := "0.1"
scalaVersion := "2.13.2"
scalacOptions ++= Seq("-unchecked", "-deprecation", "-Xcheckinit", "-encoding", "utf8", "-feature")
// Fork a new JVM for 'run' and 'test:run', to avoid JavaFX double initialization problems
fork := true
// Determine OS version of JavaFX binaries
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" % "14.0.1" classifier osName
)
HelloWorld.scala
import javafx.application.Application
import javafx.event.ActionEvent
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.layout.StackPane
import javafx.stage.Stage
// must have different name than launched Application subclass
object HelloWorldLauncher {
def main(args: Array[String]): Unit = {
new HelloWorld().mainForwarder(args)
}
}
class HelloWorld extends Application {
def mainForwarder(args: Array[String]): Unit = {
Application.launch(args: _*)
}
override def start(primaryStage: Stage): Unit = {
primaryStage.setTitle("Hello World!")
val btn = new Button
btn.setText("Say 'Hello World'")
btn.setOnAction((_: ActionEvent) => {
System.out.println("Hello World!")
})
val root = new StackPane
root.getChildren.add(btn)
primaryStage.setScene(new Scene(root, 300, 250))
primaryStage.show()
}
}
sbt run
gives following output:
$ sbt run
Warning: a legacy coursier cache was found at /home/piotrek/.coursier/cache/v1 and is currently being used.
Support for that cache location will be removed in coursier 2.0.0 final, whose release is imminent.
Follow the instructions at
https://github.com/coursier/cache-migration#cache-migration
in order to migrate your cache to the newer location.
[info] welcome to sbt 1.3.11 (AdoptOpenJDK Java 11.0.7)
[info] loading settings for project global-plugins from idea.sbt ...
[info] loading global plugins from /home/piotrek/.sbt/1.0/plugins
[info] loading project definition from /tmp/javafx-in-scala/project
[info] loading settings for project javafx-in-scala from build.sbt ...
[info] set current project to javafx-in-scala (in build file:/tmp/javafx-in-scala/)
[info] Compiling 1 Scala source to /tmp/javafx-in-scala/target/scala-2.13/classes ...
[info] running (fork) HelloWorldLauncher
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[info] Hello World!
[success] Total time: 8 s, completed 30 maj 2020, 12:24:45
Hello World!
lines shows after you click the Hello World
button.
Once again SBT uses old (pre JPMS) -classpath
switch instead of new (JPMS related) --add-modules
and the likes.