2016-07-17 8 views
5

Używanie IntelliJ Stworzyłem aplikację JavaFX, a następnie dodałem Kotlin i Maven do jej frameworków. Przyszedł z plikiem sample.fxml oraz Controller.java i Main.java. Stworzyłem nową klasę dla kontrolera w Kotlin (MainWindowController.kt) i zmieniłem nazwę pliku sample.fxml na MainWindow.fxml. I uaktualniony MainWindow.fxml wyglądać:Sterowanie FXML zawsze puste podczas korzystania z 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> 

A w moim pliku MainWindowController.kt mam:

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

Oto mój 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); 
    } 
} 

Kiedy biegnę aplikacja, której linia wydruku pokazuje, że etykieta ma wartość zerową, ale w przeciwnym razie okno pokazuje się poprawnie i widzę tekst z mojej etykiety. Null jest problemem, który mam. Nie znalazłem wiele na temat używania FXML z Kotlinem i to, co znalazłem, było trochę przestarzałe i nie wydawało się, żeby miało rzeczywiste działające rozwiązanie.

Czy ktoś wie, dlaczego etykieta jest pusta? Muszę robić coś złego lub coś nie rozumieć.

Edycja: Oto, co mam, że teraz działa Dzięki szybkiej odpowiedzi:

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

nie wiem Kotlin: Czy 'init' metodę zwaną w ramach budowy obiektu? –

+2

Powinieneś sprawdzić [TornadoFX] (https://github.com/edvin/tornadofx). To sprawia, że ​​JavaFX w Kotlin jest naprawdę fajny i ma bezpieczne DSL typu zarówno dla układu, jak i stylów. –

+2

Aby dodać komentarz @ RuckusT-Boom, obsługuje on także FXML i ładnie go usprawnia. https://github.com/edvin/tornadofx-guide/blob/master/Part%202%20-%20Usage%20Basics/10.%20FXML.md – tmn

Odpowiedz

5

Podobnie jak w przypadku konstruktorów Java, fx:id pól nie zostanie wypełnione, zanim jednak poinit (lub Java konstruktor). Typowym rozwiązaniem jest wprowadzenie do interfejsu Initializable (lub po prostu określić metodą initialize()) i do dodatkowej konfiguracji wewnątrz metody tak:

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

Pamiętaj, że w rzeczywistości nie musisz implementować 'Initializable'; proste zdefiniowanie metody 'initialize()' jest wystarczające. –

+0

Tak, to prawda! Niesamowite. Zrobiłem to krótszą drogą bez nadpisania. – GregInWI2

+0

To jest zalecany sposób, jak w [dokumentacji JavaFX] (https://docs.oracle.com/javafx/2/api/javafx/fxml/Initializable.html) w każdym razie: UWAGA Ten interfejs został zastąpiony przez automatyczny zastrzyk lokalizacji i właściwości zasobów do kontrolera. 'FXMLLoader' będzie teraz automatycznie wywoływał dowolną, opisaną przez kontroler metodę" initialize() ", opisaną bez adnotacji. Zaleca się, aby w miarę możliwości stosować metodę iniekcyjną. – Marv

6

Jak wspomniano wcześniej. Sprawdź, czy ustawiono fx: id.

Możliwe jest również użycie modyfikatora lateinit.

kod może wyglądać tak:

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

class MainWindowController { 
    @FXML 
    lateinit var helloLabel : Label 
} 
Powiązane problemy