首页 > 解决方案 > JavaFX 根加载问题

问题描述

我对 JavaFX 比较陌生。我正在尝试测试每个 fxml 都有自己的带有加载器的控制器的设计模式。

例子:。

文本.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>

<VBox>
    <children>
        <Label text="Hello world FXML"/>
    </children>
</VBox>

主控制器

public class MainController extends VBox {

    public MainController() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/test.fxml"));
        loader.setController(this);
        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

应用程序

public class App extends javafx.application.Application {

    @Override
    public void start(Stage primaryStage) {
        MainController mainController = new MainController();
        Stage stage = new Stage();
        stage.setScene(new Scene(mainController));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

这不起作用,启动应用程序时我得到一个空窗口:

在此处输入图像描述

如果对控制器和应用程序进行一些更改:

控制器

private Parent root;

public MainController() {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/test.fxml"));
    loader.setController(this);
    try {
        root = loader.load();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public Parent getRoot() {
    return root;
}

应用程序

stage.setScene(new Scene(mainController.getRoot()));

在这一切都按预期工作之后,可以在窗口中看到带有文本的标签。

如果我尝试在控制器中设置 root:

loader.setRoot(this);

我收到一个错误:

javafx.fxml.LoadException: Root value already specified.
/C:/.../target/classes/fxml/test.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
    ...

问题:任何在 JavaFX 方面有更多经验的人都可以给我建议吗?我究竟做错了什么?有没有更好的方法来实现这一目标?

标签: javafx

解决方案


由于您要使用自定义组件方法,因此您需要确保:

  • 在组件的构造函数中设置controller和加载 fxmlroot之前FXMLLoader
  • 用作<fx:root>fxml 的根元素
  • fx:controller在 fxml 中指定
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
    <children>
        <Label text="Hello world FXML"/>
    </children>
</fx:root>
public class MainController extends VBox {

    public MainController() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/test.fxml"));
        loader.setController(this);
        loader.setRoot(this);
        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

推荐阅读