Search This Blog

Saturday 29 July 2017

Hello World in JavaFX with Kotlin and Gradle

I want to make a GUI application using Kotlin. JavaFX seems to be the way to do modern GUI applications on the JVM. But how to get it all integrated? What follows is a minimal, "Hello World" application, and my instructions for getting it working on Ubuntu 16.04.

Hopefully not this complicated

Here is a link to a GitHub repository that contains the working code.

Install prerequisites

First, make sure you have JavaFX installed. I use OpenJDK on Ubuntu. OpenJDK ships as part of Ubuntu 16.04, but despite JavaFX being a part of the JRE, it doesn't ship with the standard OpenJDK package. Instead you should run:
sudo apt-get install openjfx
This will add JARs to /usr/lib/jvm/<JAVA VERSION>/lib.

I was using IntelliJ IDEA to develop and I discovered I had to do some additional steps to get it to notice I had installed JavaFX:
  1. In the newly created project, go to File → Project Structure
  2. Remove the JDK and recreate it, to make sure the classpath includes the new JavaFX jars
  3. Make sure the module is targeting Java 8
You may not have to do these steps - I created the project before installing JavaFX, which may have been the root of my problems.

Write the code

Next, the actual Kotlin code. Here's App.kt (imports elided for brevity).
fun main(args: Array)
{
    launch(JavaFXExample::class.java)
}

class JavaFXExample : Application()
{
    override fun start(primaryStage: Stage)
    {
        val layout = VBox().apply {
            children.add(Label("Hello, World!"))
        }
        primaryStage.run {
            scene = Scene(layout)
            show()
        }
    }
}
Pretty straightforward: This creates a Vertical Box layout and then adds a single Label element to it. It then creates a scene including this layout and adds it to the primary stage. (Think theatre when you are working with JavaFX: The metaphor is of a stage (a window) that shows one scene at a time).

Gradle

Finally, the gradle.build file:
buildscript {
    ext.kotlin_version = '1.1.3-2'

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "de.dynamicfiles.projects.gradle.plugins:javafx-gradle-plugin:8.8.2"
    }
    repositories {
        mavenLocal()
        mavenCentral()
    }
}

apply plugin: 'kotlin'
apply plugin: 'javafx-gradle-plugin'

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
}

jfx {
    mainClass = 'javafx.example.JavaFXExample'
    vendor = '<YOUR NAME OR COMPANY>'
}

The JavaFX Gradle Plugin has a terrifying number of features, but this is all you need to get going.

Run it!

./gradle :jfxRun

You can run the code in my repository using the Gradle wrapper included, without having to have Gradle installed, using ./gradlew :jfxRun.