我正在使用javaFX,我需要将自定义组件放到我的场景中。因此,我的“main_pane.fxml”包含我的组件的网格窗格(例如DocumentModule)。
<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="GUI.MainPane" gridLinesVisible="true" >
<padding>
<Insets bottom="0" top="0" left="0" right="0" />
</padding>
.
.
.
<DocumentModule fx:id="documentModule"
minWidth="200" minHeight="400"
GridPane.columnIndex="0" GridPane.rowIndex="1">
.
.
.
</DocumentModule>
.
.
.
每个都在单独的fxml文件中定义。
<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="GUI.DocumentModule" >
<padding>
<Insets bottom="0" top="0" left="0" right="0" />
</padding>
<ToolBar fx:id="toolBar" GridPane.rowIndex = "0" GridPane.columnIndex = "0" orientation="HORIZONTAL" >
.
.
.
</ToolBar>
<ScrollPane fx:id="scrollPane" hbarPolicy="AS_NEEDED" vbarPolicy="AS_NEEDED" GridPane.rowIndex = "1" GridPane.columnIndex = "0">
<DocumentView fx:id="documentView"/>
</ScrollPane>
</GridPane>
问题是DocumentModule在构建后没有初始化。它的构造函数被调用但不是它的初始化(URL位置,ResourceBundle资源)方法。因此,不会注入来自fxml的对象。
public class DocumentModule extends GridPane implements Initializable {
protected Document document;
@FXML
private DocumentView documentView;
@FXML
private ScrollPane scrollPane;
.
.
.
public DocumentModule() {
System.out.println("Document Module constructed.");
//this is called correctly
}
@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Document Module initialized.");
//This is not called at all.
}
}
对于MainPane,一切正常,但不适用于任何内部组件。 组件树似乎构造正确,只是内部组件未初始化。内部组件也没有在应用程序场景中显示(如果我直接加载它们的fxml,如果我使用fx:include它们只是显示)。
public final class MainPane extends GridPane implements Initializable {
@FXML
private DocumentModule documentModule;
@FXML
private EditModule editModule;
public MainPane() {
System.out.println("Main Pane constructed.");
}
@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Main Pane initialized.");
}
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("main_pane.fxml"));
GridPane root = fxmlLoader.load();
Scene scene = new Scene(root, 800, 600);
primaryStage.setMaximized(true);
primaryStage.setMinWidth(800);
primaryStage.setMinHeight(600);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
我没有找到任何相同问题的主题/页面/博客。他们中很少有类似的症状,但没有一个解决方案帮助了我。有没有人知道为什么不在内部组件上调用初始化?
谢谢! 汤姆
答案 0 :(得分:3)
您的代码中没有任何地方实际加载document_module.fxml
,因此永远不会创建在那里定义的元素。当initialize()
加载该文件时,在控制器上为fxml文件调用FXMLLoader
方法,但由于您从未加载fxml文件,因此永远不会调用initialize()
方法。
主FXML中的元素<DocumentModule>
仅导致DocumentModule
类被实例化(通过调用其无参数构造函数),但是没有从那里到fxml文件的链接。
您似乎正在尝试关注FXML custom component pattern。为此,您需要在自定义组件构造函数中加载FXML文件。指定动态root并且不在fxml中指定控制器类,并在调用load之前在FXMLLoader
上设置它们:
document_module.fxml:
<fx:root type="GridPane" xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets bottom="0" top="0" left="0" right="0" />
</padding>
<ToolBar fx:id="toolBar" GridPane.rowIndex = "0" GridPane.columnIndex = "0" orientation="HORIZONTAL" >
.
.
.
</ToolBar>
<ScrollPane fx:id="scrollPane" hbarPolicy="AS_NEEDED" vbarPolicy="AS_NEEDED" GridPane.rowIndex = "1" GridPane.columnIndex = "0">
<DocumentView fx:id="documentView"/>
</ScrollPane>
</fx:root>
DocumentModule.java:
public class DocumentModule extends GridPane implements Initializable {
protected Document document;
@FXML
private DocumentView documentView;
@FXML
private ScrollPane scrollPane;
.
.
.
public DocumentModule() {
System.out.println("Document Module constructed.");
FXMLLoader loader = new FXMLLoader(getClass().getResource("document_module.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException exc) {
exc.printStackTrace();
// this is pretty much fatal, so:
System.exit(1);
}
}
@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println("Document Module initialized.");
// This will now be called after the @FXML-annotated fields are initialized.
}
}