2016-07-17 17 views
5

IntelliJ verwenden Ich habe eine JavaFX-Anwendung erstellt und dann Kotlin und Maven als Frameworks hinzugefügt. Es kam mit einer sample.fxml-Datei und einem Controller.java und Main.java. Ich habe eine neue Klasse für den Controller in Kotlin (MainWindowController.kt) erstellt und die Datei sample.fxml in MainWindow.fxml umbenannt. Ich die MainWindow.fxml aktualisiert wie folgt aussehen:FXML-Steuerelement immer null bei Verwendung von Kotlin

<?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> 

Und in meiner MainWindowController.kt Datei ich habe:

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}") 
    } 
} 

Hier ist mein 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); 
    } 
} 

Wenn ich laufen Die App zeigt in der Druckzeile an, dass das Label null ist, aber ansonsten wird das Fenster korrekt angezeigt und ich sehe den Text von meinem Label. Die Null ist das Problem, das ich habe. Ich habe nicht viel über die Verwendung von FXML mit Kotlin gefunden, und was ich gefunden habe, war etwas veraltet und schien keine wirklich funktionierende Lösung zu haben.

Weiß jemand, warum das Label null ist? Ich muss etwas falsch machen oder etwas falsch verstehen.

Edit: Hier ist, was ich habe, dass jetzt dank der schnellen Antworten funktioniert:

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}") 
    } 
} 
+0

ich Kotlin weiß nicht: ist das 'init' Verfahren als Teil der Objektkonstruktion genannt? –

+2

Sie sollten [TornadoFX] (https://github.com/edvin/tornadofx) auschecken. Es macht JavaFX in Kotlin wirklich nett und hat sichere DSLs für das Layout und die Stile. –

+2

Um @ RuckusT-Booms Kommentar hinzuzufügen, unterstützt es auch FXML und rationalisiert es sehr schön. https://github.com/edvin/tornadofx-guide/blob/master/Part%202%20-%20Usage%20Basics/10.%20FXML.md – tmn

Antwort

5

Genau wie mit Java Bauer, fx:id Felder werden nicht vor besiedelt werden, sondern nach der init (oder in Java die Konstruktor) wird aufgerufen. Eine übliche Lösung ist es, die Initializable Schnittstelle (oder nur definiert eine initialize() Methode) und macht zusätzliche Einrichtung in der Methode zu implementieren, so wie:

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}") 
    } 
} 
+5

Beachten Sie, dass Sie "Initializable" nicht wirklich implementieren müssen; einfach eine 'initialize() 'Methode zu definieren ist genug. –

+0

Ja, das war's! Genial. Ich habe den kürzeren Weg ohne Override gemacht. – GregInWI2

+0

Das ist der empfohlene Weg gemäß der [JavaFX-Dokumentation] (https://docs.oracle.com/javafx/2/api/javafx/fxml/Initializable.html) wie auch immer: HINWEIS Diese Schnittstelle wurde durch die automatische Injektion von Standort ersetzt und Ressourceneigenschaften in den Controller. 'FXMLLoader' ruft nun automatisch jede vom Controller definierte Methode 'initialize()' ohne Kommentar auf. Es wird empfohlen, dass der Injektionsansatz wann immer möglich angewendet wird. – Marv

6

wie zuvor erwähnt. Überprüfen Sie, ob fx: id gesetzt ist.

Es ist auch möglich, lateinit Modifizierer zu verwenden.

Ihr Code könnte wie folgt aussieht:

import javafx.fxml.FXML 
import javafx.scene.control.Label 

class MainWindowController { 
    @FXML 
    lateinit var helloLabel : Label 
}