当前位置: 首页 > 知识库问答 >
问题:

JavaFX初始化()在内部自定义组件上不被调用

越雨泽
2023-03-14

我正在使用javaFX,我需要把自定义组件放到我的场景中。因此,我有“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文件中定义。

<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>

问题是DocumentModul在构建后没有初始化。它的构造函数被调用,但它的初始化(URL位置、资源包资源)方法没有被调用。因此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();
} 

我没有找到任何有同样问题的话题/页面/博客。他们中很少有人有类似的症状,但是没有溶质对我有帮助。有人知道为什么内部组件不调用初始化吗?

谢谢汤姆

共有1个答案

元嘉木
2023-03-14

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

元素

看起来您正在尝试遵循FXML自定义组件模式。为此,需要在自定义组件构造函数中加载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>

文档模块。爪哇:

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.
    }

}

 类似资料:
  • 我正在为一个从application.properties中获取值的组件编写测试。 在测试本身中,从application-test.properies中正确提取值。我使用了@testpropertysource(locations=“classpath:application-test.properties”) 然而,在测试的类中,这些值不会被拾取,并且是空值。 测试: 测试的组件: 如何使用a

  • 如何向Swift中的子类添加自定义初始化器? 我创建了的一个子类,它看起来如下所示: 如果我加上这个,Xcode会抱怨处初始化。所以我想这也不是解决办法。所以我想知道如何在Swift中将自定义初始化器正确地添加到子类中(因为在Objective-C中这似乎不是问题)?

  • 本文向大家介绍Swift使用参数自定义初始化,包括了Swift使用参数自定义初始化的使用技巧和注意事项,需要的朋友参考一下 示例 请注意,您不能省略参数标签: 为了允许省略参数标签,请使用下划线_作为标签: 如果参数标签使用一个或多个属性共享名称,请使用self显式设置属性值:            

  • Swift 5.x String初始化、定义 1. 字面量初始化字符串 1.1 单行字面量字符串 let str = "some string" 1.2 字面量初始化多行字符串 let str = """ The white Rabbit put on his spectacles. "Where shell I begin, please your Majesty?" he asked. "

  • 我一直在尝试在tkinter中创建一个自定义小部件,没什么特别的,只是一个包含一个条目和两个标签的框架。我希望标签和框架能够访问父应用程序的StringVars(即两个标签的textvariable,以及条目textvariable)。我认为通过将这些名称作为关键字args传递给初始化方法,这应该相当简单,但是我遇到了麻烦。这是我的密码: 我遇到了一个问题,我实际上无法将任何其他内容传递给我的新小