Skip to content
This repository has been archived by the owner on Sep 28, 2024. It is now read-only.

Components

Edvin Syse edited this page Jan 9, 2016 · 32 revisions

WikiDocumentationComponents

UI Component overview

The visual parts of a Tornado FX application is comprised of UI Components called View and Fragment. They behave exactly the same with one crucial difference: View is a singleton, so there will be only one instance of any given View in your application, while Fragment behaves like a prototype object, meaning that a new instance will be created every time you look one up.

Note: For all other purposes they are the same, so for brevity we will simply refer to UI Components as views from now on.

View

A View will contain your view controller logic, as well as the actual hierarchy of Java FX nodes that comprises the user interface. You can choose to build your UI with Kotlin or use FXML.

UI built with Kotlin

class HelloWorld : View() {
    override val root = HBox(Label("Hello world")) 

    init {
        root += Label("Another label")
    }
}

A Simple View with an HBox root node and additional nodes added in the init block

Kotlin views can also utilize the [type safe builders](Type Safe Builders) that comes with Tornado FX.

with(root) {
    hbox {
        label("Hello world") {
            addClass("heading")
        }

        textfield {
            promptText = "Enter your name"
        }
    }
}

Additional nodes added using the type safe builder pattern

UI built with FXML

Instead of building your UI in Kotlin directly, you can also pull in the root node from an FXML file with the same name as the view. When loading the root node from FXML you can also optionally implement the Initializable interface to do some post processing of the node hierarchy.

class HelloWorld : View() : Initializable {
    override val root: HBox by fxml()

    @FXML lateinit var myLabel: Label

    fun initialize(location: URL, resources: ResourceBundle) {
        myLabel.text = "Hello world"
    }

}

The view is loaded from FXML and the Label is injected with the @FXML annotation.

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<HBox prefHeight="200" xmlns:fx="http://javafx.com/fxml/1">
    <Label fx:id="myLabel" />
</HBox>

HelloWorld.fxml

Caveat: You cannot access the root node inside the initialize function, as the actual node is not returned from the FXMLLoader at that point. If you need to access the actual root node, either inject it by placing an fx:id attribute on it, or simply wrap the access code in a Platform.runLater { // access root here } block.

Controller

Business logic is contained in a Controller. All controllers are singletons, and can be injected into both other controllers and views.

Note: From now on, components referst to any "Controller, View or Fragment"

Controllers might perform long running tasks, and should not run on the Java FX UI thread. Calling code on the right thread can be tedius and error prone, but Tornado FX does all the heavy lifting, leaving you to focus on your business and view logic.

When to use View and when to use Fragment

When a user interface will only used in one place at a time, a View is the better choice. For popups or other short lived objects, you might consider Fragments instead. A complex view might contain both other Views and Fragments.

Clone this wiki locally