有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

来自不同FXML文件的java@FXML注释组件导致NPE

我有两个FXML文件。第一个描述显示的第一个窗格,其中包含一个选项卡窗格、一个菜单和一个菜单项,该菜单项应该在选项卡窗格中打开一个新选项卡,并在其中绘制一组新节点。 以下是代码:

public class Main extends Application {

private Pane mainRoot;
private Pane secondaryRoot;

@Override
public void start(Stage primaryStage) {
    try {
        mainRoot = (Pane) ResourceLoader
                .load("MainFXML.fxml");

        secondaryRoot = (Pane) ResourceLoader.load(("SecondaryFXML.fxml"));

        Scene scene = new Scene(mainRoot);

        primaryStage.setScene(scene);
        primaryStage.show();

        thisMain = this;

    } catch (Exception e) {
        e.printStackTrace();
    }
}

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

private static Main thisMain;

public static Main getMain() {
    return thisMain;
}
public Pane getSecondaryRootPane() {
    return secondaryRoot;
}

然后我有一个与两个FXML文件关联的控制器。因此,它将选项卡窗格作为FXML注释字段。此外,它还处理菜单项上的单击事件,即创建新选项卡的事件:

public class GUIController {
@FXML
private TabPane tabPane;

public void newTabRequest(Event e) {
    // create the new tab
    Tab newTab = new Tab("New tab");

    // set the content of the tab to the previously loaded pane
    newTab.setContent(Main.getMain().getSecondaryRootPane());

    // add the new tab to the tab pane and focus on it
    tabPane.getTabs().add(newTab);
    tabPane.getSelectionModel().select(newTab);

    initializeComboBoxValues(); // HERE I HAVE A PROBLEM
}}

控制器的最后一行调用一个方法,其代码如下:

private void initializeComboBoxValues() {
    myComboBox.getItems().add(MyEnum.myEnumValue1);
    myComboBox.getItems().add(MyEnum.myEnumValue2);
}

我有一个@FXML组合框字段,它与FXML中声明的相应组件同名,我正试图用值填充它。 问题是myComboBox结果为空。我错在哪里?我在哪里设计错了

如果有帮助的话,我想指出这一点:我在新选项卡中创建并添加了一个测试按钮。与此按钮关联的事件调用相同的InitializeComboxValues方法。好吧,这是可行的(考虑到我从newTabRequest处理程序中删除了它的调用,以避免NPE)


共 (1) 个答案

  1. # 1 楼答案

    每次使用FXMLLoader时,都会创建一个新的控制器。由于不做任何事情来连接两个控制器,因此每个控制器都只设置了@FXML注释字段,这些字段在它膨胀时位于它自己的Pane

    您必须在两个控制器之间建立某种通信,才能使其正常工作

    如果使用FXMLLoader的实例和非静态加载函数,例如,这样(不要重用FXMLLoader来加载第二个fxml文件),则可以从FXMLLoader获取控制器:

    FXMLLoader loader = new FXMLLoader();
    // be sure to use a non-static load method, like load(InputStream)
    secondaryRoot = loader.load(getClass().getResourceAsStream("SecondaryFXML.fxml"));
    FXMLDocumentController secondaryController = loader.getController(); // Change type to your controller type here
    

    然后,您可以向控制器添加一个方法,该方法允许您将另一个控制器传递给控制器。这样,您就可以从另一个控制器访问字段

    我强烈建议您为这两种布局创建不同的控制器类。否则,这只会增加混乱