我有两个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注释的字段。此外,它处理菜单项上的click事件,这是创建新选项卡的事件:

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 ComboBox字段,其名称与FXML中声明的相应组件的名称相同,并且我试图用值填充。
问题是myComboBox结果为null。我哪里错了?我在哪里设计错了?

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

最佳答案

每次使用FXMLLoader时,都会创建一个新的控制器。由于您不执行任何操作来连接两个控制器,因此每个控制器都仅设置了@FXML带注释的字段,该字段在充气时位于其自己的Pane中。

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

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

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


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

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

关于java - @FXML注释的组件来自不同的FXML文件,从而导致NPE,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24715492/

10-13 05:38