使用 Kotlin 时 FXML 控件始终为 null

FXML control always null when using Kotlin

我使用 IntelliJ 创建了一个 JavaFX 应用程序,然后将 Kotlin 和 Maven 作为框架添加到其中。它带有一个 sample.fxml 文件和一个 Controller.java 和 Main.java。我在 Kotlin (MainWindowController.kt) 中为控制器创建了一个新的 class,并将 sample.fxml 文件重命名为 MainWindow.fxml。我将 MainWindow.fxml 更新为:

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

在我的 MainWindowController.kt 文件中我有:

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

这是我的 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);
    }
}

当我 运行 应用程序时,打印行显示标签为空,否则 window 正确显示并且我看到标签中的文本。 null 是我遇到的问题。我没有找到太多关于将 FXML 与 Kotlin 结合使用的信息,而且我发现的内容有点过时并且似乎没有实际可行的解决方案。

有谁知道为什么标签为空?我一定是做错了什么或者误解了什么。

编辑:由于快速回复,这是我现在可以使用的内容:

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

就像 Java 构造函数一样,fx:id 字段不会在 之后 init 之前填充(或在 Java 构造函数) 被调用。一个常见的解决方案是实现 Initializable 接口(或者只定义一个 initialize() 方法)并在方法内部进行额外的设置,如下所示:

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

如前所述。检查是否设置了fx:id。

也可以使用lateinit修饰符。

您的代码可能如下所示:

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

class MainWindowController {
    @FXML 
    lateinit var helloLabel : Label
}