I am trying to make basic desktop app using Kotlin and JavaFX(TornadoFX), but I am stuck on setting up controller for FXML file. I am following guide from edvin on git LINK to git.
The program should increment number in label whenewer is the button clicked.
The problem is..
When I try to use FXML file shown below, I can't use onAction="#increment"
to "connect" that file with a controller.
This will compile, but there is no way to call increment function from controller.kt file. Also there is error saying "No controller specified for top level element" ..
Whenever I try to specify the controller by using fx:controller=view.Controller
the code will not even compile, showing error:
javafx.fxml.LoadException: Controller value already specified.
Could someone please help me out?
Here is FXML file:
?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets top="20" right="20" bottom="20" left="20"/>
</padding>
<center>
<VBox alignment="CENTER" spacing="10">
<Label text="0">
<font>
<Font size="20"/>
</font>
</Label>
<Button text="Click to increment" onAction="#increment"/>
</VBox>
</center>
</BorderPane>
Here is MyApp.kt (main file):
package app
import javafx.stage.Stage
import tornadofx.*
import view.MainView
class MyApp: App(MainView::class){
override val primaryView = MainView::class
override fun start(stage: Stage) {
stage.minHeight = 400.0
stage.minWidth = 600.0
super.start(stage)
}
}
Here is MainView.kt (view):
package view
import javafx.scene.layout.BorderPane
import tornadofx.*
class MainView : View() {
override val root: BorderPane by fxml("/views/MainViewFXML.fxml" )
}
Here is Controller.kt (this should be used to control FXML file actions):
package view
class Controller {
fun increment(){
//code
}
}
In TornadoFX, the View IS the controller. Think of View subclasses as the View Controller. React to UI events in the View, and pass business logic off to a ViewModel or a Controller subclass.
Place your increment
function in MainView
and it will be called :) Remove the fx:controller=view.Controller
attribute.