CLI tool
scalafx/scalafx avatar
scalafx/scalafx

ScalaFX is a Scala DSL over JavaFX, and its version numbers follow JavaFX

ScalaFX simplifies creation of JavaFX-based user interfaces in Scala

701 stars66 forksScalaNOASSERTION

At a glance

What is it?
ScalaFX wraps JavaFX in a Scala API, so a ScalaFX application is also a valid Scala application and interoperates with Java. The version scheme is the thing to understand before you depend on it, because the major version tracks the JavaFX release and the minimum JDK moves with it, so version 27 needs JDK 25.
Who is it for?
Adopt ScalaFX if you are writing a desktop UI in Scala and want the JavaFX control set with a Scala API, since the library is a thin, well-documented layer and runs anywhere the JVM and JavaFX do. Skip it if you would rather not track a JavaFX-coupled version line, since the major version moves with JavaFX and the minimum JDK requirement moves with it.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly Scala, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It is a DSL, and the DSL is the point

ScalaFX is a UI DSL written within the Scala Language that sits on top of JavaFX, and the stated consequence is that every ScalaFX application is also a valid Scala application, with full interoperability with Java, and it can run anywhere the Java Virtual Machine and JavaFX are supported.

That framing is more specific than it sounds. A DSL is not a wrapper library that hands you JavaFX objects, it is an API shaped so that the Scala idioms are the natural way to write the interface. The hello world shows the difference, and it is short enough to take in:

scala
//> using dep org.scalafx::scalafx:27.0.0-R39

import scalafx.application.JFXApp3
import scalafx.scene.Scene
import scalafx.scene.control.Label
import scalafx.scene.layout.StackPane

object HelloApp extends JFXApp3:
  override def start(): Unit =
    stage = new JFXApp3.PrimaryStage:
      title = "Hello ScalaFX"
      scene = new Scene(300, 200):
        root = new StackPane:
          children = new Label("Hello, ScalaFX!")

The `JFXApp3` trait is the entry point, and the indentation-based block syntax with `:` at the end of the line is Scala 3's significant indentation. The scene graph is built by nesting blocks rather than by passing constructors around, which is the part that makes the DSL feel like Scala rather than like JavaFX with nicer imports.

The file is run with Scala CLI using `scala-cli HelloApp.scala`, and the dependency is declared in a comment directive on the first line, which means the example needs no build file at all.

The project is Scala, with a BSD-3-Clause licence per the badge, and the last push was on 2026-10-16 with release v.27.0.0-R39 the same day.

The version number is a JavaFX version number with a suffix

The compatibility table is the single most useful thing in the documentation, and it explains the whole versioning scheme in one view.

ScalaFX 27.0.0-R39 pairs with JavaFX 27 and needs a minimum JDK of 25, supporting Scala 3.3+ as well as 2.13 and 2.12. Version 26.0.0-R38 pairs with JavaFX 26 and JDK 24, 25.0.2-R37 with JavaFX 25 and JDK 23, 24.0.2-R36 with JavaFX 24 and JDK 22, and 23.0.1-R34 with JavaFX 23 and JDK 21.

So the major version is the JavaFX version, the R suffix is the ScalaFX release within that JavaFX generation, and the minimum JDK requirement climbs with JavaFX. ScalaFX 27 requires JDK 25 or newer, and the documentation links the JavaFX 27 requirement to explain why.

That coupling has a practical consequence. When a new JavaFX release lands, a new ScalaFX major version lands with it, and the JDK floor moves up by one. If you are on an older JDK, you pin an older ScalaFX, and you are then also pinned to the JavaFX generation it was built against.

The binary suffix also means a ScalaFX patch release is not a drop-in replacement in the usual semantic versioning sense. R39 to R40 is a change within a JavaFX generation, and the version is not semver so the tooling will not tell you whether a bump is safe.

Note also that the Scala version support is wide, with 3.3+ alongside 2.13 and 2.12 on every recent line, so the Scala side is not what constrains you. The JDK and the JavaFX generation are.

How the build tool resolves JavaFX is the part that bites

There are three documented build tool setups, and the difference between them is not cosmetic.

With SBT, the dependency line is:

scala
libraryDependencies += "org.scalafx" %% "scalafx" % "27.0.0-R39"

And SBT resolves the JavaFX modules, including the platform-specific ones, through the ScalaFX dependency. There is no need to add them explicitly. That is the important sentence, because JavaFX ships platform-specific native binaries per operating system and a build that does not pull them in produces an application that cannot start.

With Mill, the JavaFX modules have to be listed by hand:

scala
//| mill-version: 1.1.10

package build
import mill._, scalalib._

object yourProject extends ScalaModule {
  def jvmId = "temurin:25" // JavaFX 27 requires JDK version >= 25
  def scalaVersion = "3.7.3"

  // Add dependency on JavaFX libraries
  val javaFxVersion = "27"
  val scalaFxVersion = "27.0.0-R39"
  val javaFxModules = List("base", "controls", "fxml", "graphics", "media", "swing", "web")

  def mvnDeps = Seq(
    mvn"org.scalafx::scalafx:$scalaFxVersion"
  ) ++ javaFxModules.map(mod => mvn"org.openjfx:javafx-$mod:$javaFxVersion")
}

Unlike SBT, Mill does not resolve the platform-specific JavaFX modules through the ScalaFX dependency, so the JavaFX modules are listed explicitly.

Gradle needs the OpenJFX plugin and the module list as well:

groovy
plugins {
    id 'scala'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.1.0'
}

repositories {
    mavenCentral()
}

javafx {
    version = "27"
    modules = ['javafx.controls', 'javafx.media']
}

dependencies {
    implementation 'org.scala-lang:scala3-library_3:3.3.8'
    implementation 'org.scalafx:scalafx_3:27.0.0-R39'
}

The `org.openjfx.javafxplugin` is the piece that makes Gradle behave like SBT here, and without it the platform natives are missing in the same way as with Mill.

So the practical rule is: with SBT you add one line, with Mill and Gradle you add a module list and a plugin. If you are switching build tools, that is the part to copy over.

The examples are the documentation, and there are a lot of them

The documentation section points at four sources of material, and the fourth is the one that teaches the library.

The ScalaFX website holds the guides, starting with For the Impatient, which the hello world section also links to for how to create a full SBT project, and a Further Resources page. The ScalaFX API is published as Scaladoc. There is a scalafx-demos directory in the repository with many small demo applications.

The demo projects and examples section then lists what the ScalaFX organisation on GitHub holds. There is scalafx-hello-world, the simplest SBT project and the recommended starting point, and ScalaFX-Hello-World-Gradle, the same thing built with Gradle. There is scalafx.g8, a Giter8 template for new ScalaFX projects, used with `sbt new scalafx/scalafx.g8`, which is the fastest way to start a project with the build already configured. There is ScalaFX-Tutorials, examples of using ScalaFX each in a small standalone project.

And then two large ones. scalafx-ensemble is a gallery of over 60 sample applications covering controls, charts, graphics, media and web views, with their source code. ProScalaFX holds examples from the Pro JavaFX books translated to ScalaFX. And scalafx-extras holds additions to ScalaFX that do not have corresponding concepts in JavaFX, with demos.

That last project is the interesting one for understanding the relationship. JavaFX has a fixed control set, and any UI idea that does not map onto it needs a custom component. scalafx-extras is where those live, and it means the answer to does ScalaFX have a control for X is sometimes in a second repository rather than in the main one.

The ensemble gallery, incidentally, is also the fastest way to judge whether the API feels right to you, since sixty screens of ordinary UI code is a better sample than one hello world.

What the repository layout says about the project

The tree is that of a mature Scala project, and a few entries are worth pointing at.

There is the scalafx/ directory holding the library itself, and scalafx-demos/ for the small demo applications that ship in the same repository. The project/ directory is the SBT build definition, and build.sbt is the build. The docs/ directory holds the documentation sources that generate the website, and notes/ holds the design notes.

The version is not in build.sbt. There is a version.sbt file, which in SBT convention is the place a project keeps its version so that the release tooling can read and bump it, and the release tags follow the same pattern as the Maven artifact, v.27.0.0-R39 and the two before it.

The tooling files are the ordinary modern Scala set. There is a .scalafmt.conf for the formatter, .sbtopts and .jvmopts for the build tool's own options, and an .editorconfig. The CI is a GitHub Actions workflow for Scala, and there is a .github/ directory for the rest.

The documentation tells you where to ask. Have a question or an idea? Join us in ScalaFX Discussions, and the repository also has a Discussions badge in the header, which is a sign that the project expects its questions to be answered in public rather than in a tracker.

The project is published to Maven Central as org.scalafx:scalafx_3, and the Scaladoc badge points at the same artifact coordinates.

Overall this is a library that has been following JavaFX closely for a long time, and the practical consequence for a new user is that you adopt it alongside a JavaFX generation rather than independently of one.

Editorial conclusion

Adopt ScalaFX if you are writing a desktop UI in Scala and want the JavaFX control set with a Scala API, since the library is a thin, well-documented layer and runs anywhere the JVM and JavaFX do. Skip it if you would rather not track a JavaFX-coupled version line, since the major version moves with JavaFX and the minimum JDK requirement moves with it. Verify first that your JDK is new enough for the ScalaFX version you pick, that your build tool resolves the platform-specific JavaFX modules correctly, which SBT does through the ScalaFX dependency and Mill and Gradle do not, and that the Scala versions you need are supported by the release you choose.

Frequently asked questions

How do I add ScalaFX to an SBT project?

Add `libraryDependencies += "org.scalafx" %% "scalafx" % "27.0.0-R39"`. SBT resolves the JavaFX modules, including the platform-specific ones, through the ScalaFX dependency, so there is no need to add them explicitly.

What JDK and Scala versions does the current ScalaFX release need?

ScalaFX 27.0.0-R39 requires JDK 25 or newer, which is a JavaFX 27 requirement, and supports Scala 3.3+ as well as 2.13 and 2.12. The compatibility table shows the pattern, with 26.0.0-R38 needing JDK 24 for JavaFX 26 and 25.0.2-R37 needing JDK 23 for JavaFX 25.

How do I run a minimal ScalaFX application?

Save it as HelloApp.scala and run it with Scala CLI using `scala-cli HelloApp.scala`, with the dependency declared in a `//> using dep org.scalafx::scalafx:27.0.0-R39` directive. The app extends JFXApp3, sets a stage in start(), and builds a scene with a StackPane and a Label.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. scalafx/scalafx on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/scalafx-scalafx.svg)](https://hysenlabs.com/projects/scalafx-scalafx)

Was this useful?