El control FXML siempre es nulo cuando se usa Kotlin

Usando IntelliJ, creé una aplicación JavaFX y luego agregué Kotlin y Maven como frameworks. Viene con un file sample.fxml y un Controller.java y Main.java. Creé una nueva class para el controller en Kotlin (MainWindowController.kt) y cambié el nombre del file sample.fxml a MainWindow.fxml. Actualicé MainWindow.fxml para que se vea así:

<?import javafx.scene.control.Label?> <?import javafx.scene.layout.GridPane?> <GridPane fx:controller="reader.MainWindowController" xmlns:fx="http://javafx.com/fxml" xmlns="http://javafx.com/javafx/8" alignment="center" hgap="10" vgap="10"> <Label fx:id="helloLabel" text="Hello"/> </GridPane> 

Y en mi file MainWindowController.kt tengo:

 package reader import javafx.fxml.FXML import javafx.scene.control.Label class MainWindowController { @FXML var helloLabel: Label? = null init { println("Label is null? ${helloLabel == null}") } } 

Aquí está mi Main.java:

 import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception{ Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("MainWindow.fxml")); primaryStage.setTitle("My App"); primaryStage.setScene(new Scene(root, 1000, 600)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

Cuando ejecuto la aplicación, la línea de printing muestra que la label es nula, pero de lo contrario la window se muestra correctamente y veo el text de mi label. El nulo es el problema que estoy teniendo. No he encontrado mucho sobre el uso de FXML con Kotlin y lo que encontré estaba un poco desactualizado y no parecía tener una solución de trabajo real.

¿Alguien sabe por qué la label es nula? Debo estar haciendo algo mal o mal entendiendo algo.

Editar: Esto es lo que tengo que ahora funciona gracias a las respuestas rápidas:

 package reader import javafx.fxml.FXML import javafx.scene.control.Label class MainWindowController { @FXML var helloLabel: Label? = null fun initialize() { println("Label is null? ${helloLabel == null}") } } 

Al igual que con los constructores de Java, los campos fx:id no se rellenarán antes, pero después de que se init el init (o en Java, el constructor). Una solución común es implementar la interfaz de Initializable (o simplemente definir un método de initialize() ) y realizar una configuration adicional dentro del método de esta manera:

 import javafx.fxml.FXML import javafx.scene.control.Label class MainWindowController : Initializable { @FXML var helloLabel: Label? = null override fun initialize(location: URL?, resources: ResourceBundle?) { println("Label is null? ${helloLabel == null}") } } 

Como se mencionó antes. Compruebe si fx: id está configurado.

También es posible usar el modificador lateinit .

Tu código podría verse así:

 import javafx.fxml.FXML import javafx.scene.control.Label class MainWindowController { @FXML lateinit var helloLabel : Label } 
  • Kotlin Lambda no está llamando al código dentro
  • Cambio observable a condición cumplida - RxJava2
  • La creación de la aplicación Kotlin falló debido a "No se pudo inicializar la class com.intellij.ide.highlighter.JavaFileType"
  • Spring Boot con Jetty + Jersey siempre muestra 404
  • Kotlin: Declarar subclasss de una Actividad estática
  • Kotlin - lateinit VS Cualquiera? = nulo
  • El complemento IdeaVim de IntelliJ inhabilita la conversión de Java a Kotlin
  • Verificación nula en caso de condiciones
  • Las variables de desestructuración de Kotlin no funcionan con Pair, Triple o Data Class
  • ¿Cuál es la coincidencia de versión correcta entre kotlin-gradle-plugin y kotlin-js-library?
  • Cómo convertir este código de iOS swift a Android Kotlin