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 } 
  • ¿Cómo se implementa la aplicación fetch?
  • java.lang.NoClassDefFoundError: com.example.api.retrofit.AuthenticationInterceptor $ intercepte $ 1
  • Desadaptación del tipo de Kotlin: ¡tipo inferido es Ver! pero se esperaba TextView
  • kotlin y @Valid Spring anotación
  • retroadaptación de kotlin: barrido de marcas simultáneas adhesivas de background GC liberado 65326 (1448 KB) objects AllocSpace, 62 objects (1736 KB),
  • Usando Kotlin en una biblioteca de Android distribuida como AAR
  • Error de compilation de Android 3.0 Canary: Versión major.minor no compatible 52.0
  • ¿Cómo determinar si un object es henetworkingado de cierta class en Kotlin?
  • Una confusión sobre Int :: class.java.isInstance () en Kotlin
  • ¿Por qué no puedo usar lambda para la interfaz en kotlin?
  • IntArray vs Array <Int> en Kotlin