Introduction to TornadoFX Part 1

Amanda Hinchman
Kotlin Thursdays
Published in
8 min readMay 23, 2018

--

Michael Levin and I grabbed coffee a few weeks ago discussing what we might do with Orlando JUG (thanks to gmail for the offer for a TornadoFX workshop being shoved in my spam email for weeks). We started up a KotlinTown group in CodeTown for anyone interested in meeting other JUG members of all levels — introductory and experienced Java users alike!

One of the things I wanted to start doing with KotlinTown is Kotlin Tuesdays: we’re still figuring out a format — I’d like to get a chat successfully set up for Kotlin use only, but in the meantime, I’m posting both here and there and if you’re interested in joining the community, comment below or message us!

TornadoFX was created by Edvin Syse, who leveraged Kotlin to create a framework for JavaFX. TornadoFX was my first love with Kotlin, and I highly recommend checking out my other posts or even Github for other really cool projects people have done playing with TornadoFX. As a developer with extensive experience in large-scale web development, I definitely have JS fatigue with the amount of new frameworks that seem to come out every year. I’m not the only one either, Mike Hearn’s post on It’s Time to Kill the Web sounds more plausible by the day.

THAT ASIDES I am not here to argue web v. native development. TornadoFX is really fun and is a small framework (hence, short learning curve), and it’s a great way to start learning Kotlin without being bogged down by servers or mobile or web development. Ya’ll ready? Good. You’re not required to know JavaFX to get started with native application development, and I’ll be providing Kotlin and TornadoFX documentation below. Documentation for TornadoFX also has extensive examples with a convenient search function for you to browse around.

Today, we create a cat-sitter scheduler for Tim, the friendly neighborhood cat-sitter, who just can’t keep his cats straight.

Feel free to refer to my public Github repo Neighborhood Cat Scheduler for the full project itself, I personally find it helpful to view the project in full when learning.

Intended finished portion for the project.

Topics Covered

  • Kotlin: basic syntax, idioms, Kotlin convention, and Maven IntelliJ setup. Let me know if I didn’t explain anything and I’ll be sure to answer and update!
  • TornadoFX: dependency injection, MVC (Model-View-Controller), type-safe CSS builders

Documentation Reference

Setup

As a JetBrains developed open-source language, it’s only a natural choice to use Community IntelliJ: go ahead and download/update if you need to.

  1. On IntelliJ, go to Preferences > Plugins and make sure Kotlin and TornadoFX is installed.

2. General consensus among TorandoFXers is that Maven is a lot easier to use — if you’re not familiar with Gradle v. Maven, don’t worry about it. It is not necessary to understand how to use either for this project, but don’t hesitate to ask for questions on setup if you run into a blocker. Once you have your plugins downloaded, open a new project and select the tornadofx-maven-plugin, which will mostly set up your project immediately.

3. It seems like the latest update for Kotlin didn’t pick up the latest running update for your Kotlin version (if you’re not sure what version you’re running, check your plugins for the latest i.e. 1.2.41). Go into your pom.xml file to edit the version and click “Import Changes” below. If it’s builds successfully, you’re good to go!

4. You’ll need to set up minimal configuration to run an instance of your application: luckily, the TornadoFX Maven plugin already did most of the painful setup for you. Go to Run > Edit Configurations, and add a new TornadoFX Configuration. Just name your config something meaningful and grab the MyApp class address, since that is already set up to launch the app. $MODULE_DIR$ detects the source of your project in your computer so you don’t have to dig for an address. Add the 1.8 JDK to the JRE and the name of your project to the classpath of the module, then hit Apply and OK. If you don’t have 1.8 JDK, you’ll need to download it from Oracle.

5. Press “Run” (or the green arrow) and you’ll see an instance of the skeleton application!

Neighborhood Cat Scheduler

Not too bad, right? The setup is always the worst part of a project.

Creating the Neighborhood with a GridPane

While TornadoFX has a lot of great components made specifically for the framework like Datagrid or Datepicker, already pre-made for your ease of use, I want to create my own neighborhood with specific streets and houses and I want full control of what goes in each block, so I will use the JavaFX GridPane written with TornadoFX DSLs. You’ll notice that you already have an app and view folder in your project — you’ll want to add a controller and model folder as well for easy organization. If you’re not familiar with MVC, the structure is a general architectural pattern developers have come up with to work with large frameworks, all split to handle different aspects of the application.

  • Models: the manipulation of data in an object-oriented formatting for the ease of use for your controllers and views.
  • Views: components used for the UI logic of your application — what you look at.
  • Controllers: acts as an interface between the model and the view the processes logic and incoming requests, ultimately carrying the heavyweight for the problem solving in your code.

What I had was house icons I downloaded from a free icon site — you’re welcome to use the ones in my project or find your own. Downloading free icons is great especially since I’m not a graphic designer myself. TornadoFX has all the features JavaFX has, if you want to know how to do something, look up Oracle JavaFX documentation/examples and transfer it to Kotlin! Here’s why I love Kotlin — in JavaFX, a gridpane is typically created like so:

A JavaFX rendering of GridPane with a single row

Given that I want to have crossing streets and houses placed in different parts of the grid, this code can grow redundant quickly. With TornadoFX and Kotlin, you can easily use DSLs to create an equivalent layout and easily add properties with apply to the parent. In Kotlin, you’ll notice that the code is a lot easier to read, and there are a couple syntactic things you see right away:

  • no semicolons: in Kotlin, you start a new line for a new thought.

variable initiation: Kotlin follows the format (val/var) name: type where val is a variable that cannot be changed whereas a var can

  • looping: Kotlin has different forms of looping that is shorter and has stronger conditionals like when(x) { 1 -> something} or foreach() you can take advantage of. This example is exactly the same as your typical for-loop like the one above in Java.
  • components: TornadoFX has a simplified way of initiating JavaFX as well as its own updated components either as component(parameters) or component{ additional components/properties }
A TornadoFX rendering of the above example.

That being said, I want to separate my individual components in the controller for function logic and create a quick and dirty version of my GridPane. You can test your results with the run every time. Below, are some more notible features for TornadoFX:

  • extension functions: much like #C, you’re able to extend methods from classes in Kotlin without having to inherit them or use a design pattern. If there’s something you need and we don’t currently have, you can spin it up quickly like the random() function created below!
  • apply{ }: accepts the receiver as an instance, and you can use this object and do anything with it! In the Controller, you can use the DSL from anywhere, but you can only create the root node with the builder syntax from a UIComponent. Once you’re “inside” any EventTarget subclass, the builders are available.
  • dependency injection: TornadoFX allows you to easily manage your code into different pieces with by inject();
  • type-safe CSS builders: using Kotlin companion objects, TornadoFX can easily create CSS customizing your objects much like CSS in web development without worrying about the type of component you use.
A Basic Neighborhood with View, Controller, and Styles classes

Build your neighborhood however you like:

Cat Schedule

One of the neat things about TornadoFX streamlines complex JavaFX layouts, including tabpane and tableview. The following is seriously crash course on some of these concepts, so I’m attaching documentation for the model creation and binding for the following result:

  • Kotlin null-safety: Kotlin allows for the ability to guarantee that your variables can never be null — val ownerName: String? = null is an example of a nullable variable in Kotlin, and the ? implements null safety by returning a null or not-null without throwing an NPE
  • ModelViewItems: TornadoFX works well with any kind of architectural patterns other than MVC. With JavaFX, models are difficult to implement and even more difficult to bind to UI Components and manipulate that logic that reflects those changes in the UI. ItemViewModel greatly reduces otherwise redundant syntax and makes binding objects to forms or tables and the like a synch.
  • Nesting views: When you call find, the TorandoFX component corresponding to the given class is looked up in a global component registry. If it did not exist prior to the call, it will be created and inserted into the registry before the function returns.

End result:

We have a lot of neat things going, but there’s a lot more we could do from here: for example, the cats avis might change per selection, and maybe we want to be able to edit our schedule. A friend of my recommended I make this canine-compatible as well: I’m inclined to agree since I’m more of a dog person myself. I’d like to be really ambitious and connect those actions with the houses as well — what are your ideas with the project?

Notes:

Still working on setting up KotlinTown properly, but if you’re interested in joining the discussion, come join us in CodeTown, the software developer community!

Are you having a blast? Continue on to part 2 of the TornadoFX tutorial: https://medium.com/@hinchman_amanda/kotlin-thursdays-introduction-to-torandofx-part-2-c6360d1283a2

--

--

Amanda Hinchman
Kotlin Thursdays

Kotlin GDE and Android engineer. Co-author of O'Reilly's "Programming Android with Kotlin: Achieving Structured Concurrency with Coroutines"