JavaFX根加载问题

时间:2018-11-15 11:58:56

标签: javafx

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

示例:。

text.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>

MainController

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();
    }
}

这不起作用,启动应用程序时出现一个空窗口:

enter image description here

如果对控制器和应用进行了某些更改:

控制器

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方面有更多经验的人可以就此建议我吗?我究竟做错了什么?有没有更好的方法可以做到这一点?

2 个答案:

答案 0 :(得分:3)

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

    在将fxml加载到组件的构造函数中之前,
  • controller设置rootFXMLLoader
  • 使用<fx:root>作为fxml的根元素
  • 不要在fxml中指定fx:controller
<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);
        }
    }
}

答案 1 :(得分:-1)

在第一个示例中,您调用了'loader.load()',但没有使用该方法的返回值。您可以尝试this.getChildren().add(loader.load())

关于调用setRoot时的异常,您可以显示所有相关代码吗?