-
Notifications
You must be signed in to change notification settings - Fork 272
Components
Wiki ▸ Documentation ▸ Components
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.
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.
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 theinit
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
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.
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 refers to any "Controller
, View
or Fragment
". They all extend the Component
base class
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 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
.