有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

fxml中定义的java自定义控件如何获取父ID?

我有一个自定义控件,定义如下:

<fx:root type="javafx.scene.Group" xmlns:fx="http://javafx.com/fxml" fx:controller="com.theCorp.theTool.controllers.LimitsController">
  <Group id="Group" layoutX="0.0" layoutY="0.0">
    <children>
        <Group id="Count" layoutX="0.0" layoutY="20.0">
            <children>
                <Label layoutX="0.0" layoutY="3.0" prefWidth="59.0" text="Count" />
                <TextField id="Count.Min" fx:id="countMin" layoutX="59.0" layoutY="0.0" prefWidth="132.0" promptText="Min" />
                <TextField id="Count.Max" fx:id="countMax" layoutX="191.0" layoutY="0.0" prefWidth="132.0" promptText="Max" />
            </children>
        </Group>
        <Button id="SaveButton" fx:id="saveButton" layoutX="12.0" layoutY="85.0" mnemonicParsing="false" onAction="#save" text="Save" />
    </children>
  </Group>
</fx:root>

我有一个Control类,它以通常的方式加载:

public class LimitsControl extends Group {
  private static final String fxmlFileName = "Limits.fxml";

  public LimitsControl() {
    super();
    URL fxml = getClass().getResource(fxmlFileName);
    if (fxml == null) {
      fxml = getClass().getResource("/fxml/" + fxmlFileName);
    }
    // Create the loader.
    FXMLLoader loader = new FXMLLoader(fxml);
    loader.setRoot(this);
    try {
      // Load the fxml.
      loader.load();
      // Pull back the controller.
      LimitsController controller = loader.getController();
      // Tell it about me.
      controller.setControl(this);
    } catch (IOException exception) {
      throw new RuntimeException(exception);
    }
  }

}

我有一个Controller类,看起来有点像这样:

public class LimitsController implements Initializable {
  // Control.
  private LimitsControl control;

  @FXML
  private TextField countMin;
  @FXML
  private TextField countMax;
  @FXML
  private Button saveButton;

  /**
   * Initializes the controller class.
   *
   * @param url
   * @param rb
   */
  @Override
  public void initialize(URL url, ResourceBundle rb) {
    log.info("Loading: " + url + " rb=" + rb+" control="+control);
    // Make the save button call my save.
    saveButton.setOnAction((ActionEvent e) -> {
      save(e);
    });
  }


  public void setControl(LimitsControl control) {
    log.info("Control="+control);
    this.control = control;
  }

  @FXML
  private void save(ActionEvent event) {
    // What is the ID of me?
    Parent myGroup = saveButton.getParent();
    // Pull the id of the control that enclosed my group.
    String myId = myGroup.getParent().getId();
    log.info("Saving: " + myId);
  }

}

我在场景中的几个地方插入这些控件,每次都使用不同的id,如下所示:

        <TitledPane fx:id="Today" animated="false" text="Today">
          <tooltip>
            <Tooltip text="Parameters will only be used for today." />
          </tooltip>
          <content>
            <LimitsControl id="Today.Limits" />
          </content>
        </TitledPane>

我的问题是,这些控件必须从需要控件的id的数据填充,但是当控制器初始化时,它没有父控件

按下save按钮时,id可用-请参阅save方法爬升父树以收集控件的id。遗憾的是,父级在初始化时为空

当父id可用时,如何正确初始化字段?还是我做错了,有办法


共 (1) 个答案

  1. # 1 楼答案

    首先,注入控件,而不是将所有内容与set方法耦合:

    <fx:root type="javafx.scene.Group" xmlns:fx="http://javafx.com/fxml" fx:controller="com.theCorp.theTool.controllers.LimitsController" fx:id="control">
    

      // Control.
      @FXML
      private LimitsControl control;
    

    如果我理解正确,您试图获取的id是LimitsControl本身的id。要使其“尽早”可用,请在LimitsControl的构造函数中定义一个参数并在其中设置id:

      public LimitsControl(String id) {
        super();
        setId(id);
            // code as before...
          }
    

    现在,由于您不再具有默认构造函数,因此需要为LimitsControl创建一个生成器:

    public class LimitsControlBuilder {
        private String id ;
        private LimitsControlBuilder() {
            this.id = "" ;
        }
        public static LimitsControlBuilder create() {
            return new LimitsControlBuilder();
        }
        public LimitsControlBuilder id(String id) {
            this.id = id ;
            return this ;
        }
    
        public LimitsControl build() {
            return new LimitsControl(id);
        }
    }
    

    现在你可以做了

    <LimitsControl id="Today.Limits" />
    

    一旦调用构造函数,它就会被设置

    当然,您可以在这里创建自己的属性,而不是使用id,这可能是fxml向自定义控件实例传递信息的一种比使用css id更合适的方式