Generic article thumbnail

Building Three-Layered JavaFX Apps with TornadoFX and Kotlin

by tb
Published:

1. Setting up the Project with Gradle or Maven

1.1 Gradle Setup

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.5.21'
    id 'org.openjfx.javafxplugin' version '0.0.10'
}

repositories {
    mavenCentral()
}

javafx {
    version = "17"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

dependencies {
    implementation 'no.tornado:tornadofx:1.7.20'
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
}

1.2 Maven Setup

<properties>
    <tornadofx.version>1.7.20</tornadofx.version>
    <kotlin.version>1.5.21</kotlin.version>
    <javafx.version>17</javafx.version>
</properties>
 
<dependencies>
    <dependency>
        <groupId>no.tornado</groupId>
        <artifactId>tornadofx</artifactId>
        <version>${tornadofx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-stdlib-jdk8</artifactId>
        <version>${kotlin.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>${javafx.version}</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>${javafx.version}</version>
    </dependency>
</dependencies>

2. Creating a Simple View Class

2.1 Basic View

import tornadofx.*
 
class MyView : View() {
    override val root = vbox {
        label("Hello, TornadoFX!")
        button("Click me") {
            action {
                println("Button clicked!")
            }
        }
    }
}

2.2 Adding Styles

class MyStyledView : View() {
    init {
        importStylesheet(Styles::class)
    }
 
    override val root = vbox {
        label("Styled TornadoFX View") {
            addClass(Styles.heading)
        }
        button("Click me") {
            addClass(Styles.button)
            action {
                println("Styled button clicked!")
            }
        }
    }
}

3. Implementing Three-Layered Architecture

3.1 Model Class

data class Person(val name: String, val age: Int)

3.2 Controller Class

import tornadofx.*
 
class MyController : Controller() {
    val persons = mutableListOf<Person>().observable()
 
    fun addPerson(name: String, age: Int) {
        persons.add(Person(name, age))
    }
}

3.3 View with Dependency Injection

class PersonListView : View() {
    val controller: MyController by inject()
 
    override val root = vbox {
        label("Person List")
        tableview(controller.persons) {
            column("Name", Person::name)
            column("Age", Person::age)
        }
        hbox {
            textfield {
                promptText = "Name"
                var name = text
            }
            textfield {
                promptText = "Age"
                var age = text.toIntOrNull()
            }
            button("Add") {
                action {
                    val name = name
                    val age = age
                    if (name != null && age != null) {
                        controller.addPerson(name, age)
                    }
                }
            }
        }
    }
}

4. Styling with CSS

4.1 Stylesheet

import tornadofx.*
 
class Styles : Stylesheet() {
    companion object {
        val heading by cssclass()
        val button by cssclass()
    }
 
    init {
        heading {
            fontSize = 20.px
            fontWeight = FontWeight.BOLD
        }
        button {
            padding = box(10.px, 20.px)
            fontSize = 14.px
        }
    }
}

Conclusion

In this tutorial, we explored the basics of building a three-layered JavaFX application using TornadoFX and Kotlin. We covered project setup, creating views with styling, implementing a three-layered architecture with models, controllers, and views, and finally, we added CSS styles to enhance the visual appeal of the application. This tutorial provides a solid foundation for developing robust and well-structured desktop applications with TornadoFX and Kotlin.