我有两个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/