Vítejte v dalším díle věnovaném jazyku Kotlin, kde si ukážeme, jak psát nabušené GUÍ-tka založené na JavaFX za pomocí výborného frameworku TornadoFX. Náš výsledek bude vypadat takto a celé nakódění nám nezabere déle jak 30 minut:
Zrovna jsem se vrátil z kite kurzu a jako obvykle si potřebuju vyúčtovat proplacení benzínu za cestu na spot a zpět. Zatímco jiní lidé by si udělali nějakou šablonku v Excelu, já jsem si na to rovnou napsal malou GUI aplikaci v Kotlinu, protože to až tolik nezabolí a výsledek prostě stojí za to! 🙂 Nejde však pouze o samotné GUI, ale taky o krásnou reaktivní funkcionalitu, resp. TornadoFX je natolik skvělé, že možnost psát GUI o sofistikovanosti nějaké soudobé ReactJS aplikace na webovém frontendu nyní přechází i na desktop. Bude potřeba jediná závislost (mimo klasický Kotlin základ), a sice:
<dependency> <groupId>no.tornado</groupId> <artifactId>tornadofx</artifactId> <version>1.7.15</version> </dependency>
A nyní již zbývá napsat následujících 85 řádků kódu do jediného souboru:
package com.svetylkovo.fuelrefund import javafx.application.Application import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleStringProperty import tornadofx.* import kotlin.math.roundToInt class Spot(val name: String, val distance: Double) { override fun toString() = name } class FuelRefund : View("Fuel Refund App") { private val spots = listOf( Spot("Příbor", 24.0), Spot("Veselák", 101.0) ).observable() private val selectedSpot = SimpleObjectProperty<Spot>() private val consumption = SimpleDoubleProperty(0.0) private val distance = SimpleDoubleProperty(0.0) private val fuelPrice = SimpleDoubleProperty(0.0) private val result = SimpleStringProperty("") override val root = vbox { prefWidth = 400.0 prefHeight = 400.0 form { fieldset("Input parameters") { field("Spot:") { combobox(selectedSpot, spots) } field("Distance:") { textfield(distance) label("km") } field("Consumption:") { textfield(consumption) label("1l/100km") } field("Fuel price (1l):") { textfield(fuelPrice) label("Kč") } } fieldset("Result:") { textarea(result) } button("Copy to clipboard").action { clipboard.putString(result.get()) } } } private fun computePrice() { val consumption = consumption.get() val distance = distance.get() val fuelPrice = fuelPrice.get() val priceResult = (consumption/100) * distance * fuelPrice result.set("($consumption/100) * $distance * $fuelPrice = ${priceResult.roundToInt()} Kč") } init { selectedSpot.onChange { distance.set(it?.distance ?: 0.0) } distance.onChange { computePrice() } consumption.onChange { computePrice() } fuelPrice.onChange { computePrice() } selectedSpot.set(spots.first()) } } class FuelRefundApp : App(FuelRefund::class) { companion object { @JvmStatic fun main(args: Array<String>) { Application.launch(FuelRefundApp::class.java) } } }