在 FXML 中使用 fx:id 作为 CSS id

Using fx:id as CSS id in FXML

似乎在 FXML 中,如果您不指定 ID (CSS),则默认使用 fx:id 值。我之前的理解是两者完全不相交,ID为CSS,只有CSS。 fx:id 用于控制器中的 @FXML 绑定。

这可以通过一个小测试来演示 - 三个按钮,第一个带有 ID,第二个带有 FX:ID,第三个带有两种类型的 ID。

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Button id="cssid0" mnemonicParsing="false" text="Button" />
      <Button fx:id="fxid1" mnemonicParsing="false" text="Button" />
      <Button id="cssid2" fx:id="fxid2" mnemonicParsing="false" text="Button" />
   </children>
</VBox>

使用 Node.lookup(cssSelector) 允许通过 fx:id

选择
@Override
public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/foo.fxml"));
    Parent p = loader.load();

    System.out.println(p.lookup("#cssid0")); // => Button[id=cssid0, styleClass=button]'Button'
    System.out.println(p.lookup("#fxid1"));  // => Button[id=fxid1, styleClass=button]'Button'

    System.out.println(p.lookup("#fxid2"));  // => null (if there is a CSS ID it takes precedent)
    System.out.println(p.lookup("#cssid2")); // Button[id=cssid2, styleClass=button]'Button'

    stage.setScene(new Scene(p, 200, 200));
    stage.getScene().getStylesheets().add("/foo.css");
    stage.show();
}

另外 CSS 允许 fx:ID

选择
#cssid0 {
    -fx-color: red;
}
#fxid1 {
    -fx-color: green;
}
#cssid2 {
    -fx-color: blue;
}

现有问题 What's the difference between fx:id and id: in JavaFX?, Javadoc for Node.getId() 或我能找到的任何其他问题似乎都没有涵盖。

此功能非常有用,因为我们只需要指定一个 fx:id 即可用于控制器,CSS 和使用 test-FX 的单元测试。

是否可以使用这种方法,或者我是否在对未记录的行为进行假设,这些行为可能会在以后的版本中发生变化?或者它是否记录在我遗漏的地方?

IMO 在 Introduction to FXML :: Variable Resolution 中有部分记录。但乍一看不是很明显:

Assigning an fx:id value to an element creates a variable in the document's namespace that can later be referred to by variable dereference attributes ...

Additionally, if the object's type defines an "id" property, this value will also be passed to the objects setId() method.

它应该用“如果对象定义了 idProperty 并且尚未设置......”来完成。基于相关的源代码在 FXMLLoader 的第 708 行:

        // Add the value to the namespace
        if (fx_id != null) {
            namespace.put(fx_id, value);

            // If the value defines an ID property, set it
            IDProperty idProperty = value.getClass().getAnnotation(IDProperty.class);

            if (idProperty != null) {
                Map<String, Object> properties = getProperties();
                // set fx:id property value to Node.id only if Node.id was not
                // already set when processing start element attributes
                if (properties.get(idProperty.value()) == null) {
                    properties.put(idProperty.value(), fx_id);
                }
            }
            ...
        }

我认为以这种行为为基础是可以的。