【问题标题】:JavaFX initialize() is not called on inner custom component内部自定义组件上未调用 JavaFX initialize()
【发布时间】:2016-06-27 06:08:24
【问题描述】:

我正在使用 javaFX,我需要将自定义组件放入我的场景中。因此,我有“main_pane.fxml”和包含我的组件的网格窗格(例如 DocumentModule)。

main_pane.fxml

<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 文件中定义。

document_module.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 在构建后没有初始化。它的构造函数被调用,但不是它的 initialize(URL location, ResourceBundle resources) 方法。因此不会注入来自 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,它们只会显示)。

MainPane 控制器

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

我没有找到任何有同样问题的主题/页面/博客。他们中很少有人有类似的症状,但没有一种解决方案对我有帮助。有谁知道为什么不对内部组件调用初始化?

谢谢! 汤姆

【问题讨论】:

  • 我发现我的 XML 文件中缺少 fx:controller="sample.Controller" 用于第一个 AnchorPaneVBox 或任何您开始 XML 布局的内容。它找不到Controller类来从内部调用initialize函数。

标签: java javafx


【解决方案1】:

您的代码中没有任何地方实际加载document_module.fxml,因此永远不会创建在那里定义的元素。当FXMLLoader 加载该文件时,在控制器上为fxml 文件调用initialize() 方法,但由于您从未加载fxml 文件,因此永远不会调用initialize() 方法。

主 FXML 中的元素 &lt;DocumentModule&gt; 仅导致 DocumentModule 类被实例化(通过调用其无参数构造函数),但没有从那里到 fxml 文件的链接。

您似乎正在尝试遵循 FXML custom component pattern。为此,您需要在自定义组件构造函数中加载 FXML 文件。在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.
    }

}

【讨论】:

  • 谢谢!有趣的是,我之前使用过这种方式(fx:root 并在构造函数中设置控制器和 root),但我无法让它工作。可能还有其他一些错误通过在那里重写而消失了。再次感谢您。
  • 用 @FXML 注释 intialize()。
猜你喜欢
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
相关资源
最近更新 更多