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

Ada*_*dam 7 javafx javafx-8

看来在FXML中如果没有指定ID(CSS),则默认使用fx:id值.我之前的理解是两个完全不相交,CSS的CSS和只有CSS.fx:控制器中@FXML绑定的id.

这可以通过一个小测试来证明 - 三个按钮,首先是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>
Run Code Online (Sandbox Code Playgroud)

使用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();
}
Run Code Online (Sandbox Code Playgroud)

CSS也允许通过fx:ID进行选择

#cssid0 {
    -fx-color: red;
}
#fxid1 {
    -fx-color: green;
}
#cssid2 {
    -fx-color: blue;
}
Run Code Online (Sandbox Code Playgroud)

这似乎没有被现有问题所涵盖fx:id和id:在JavaFX中有什么区别?,Node.getId()的 Javadoc 或我能找到的任何其他地方.

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

是否可以使用这种方法,或者我是否建立了可能在以后的版本中发生变化的未记录行为的假设?或者它记录在某个我遗失的地方?

Ulu*_*Biy 4

IMO 部分记录在FXML :: 变量解析简介中。但乍一看并不那么明显:

将 fx:id 值分配给元素会在文档的命名空间中创建一个变量,稍后可以通过变量取消引用属性来引用该变量...

此外,如果对象的类型定义了“id”属性,则该值也将传递给对象的 setId() 方法。

它应该以“如果对象定义了 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);
                }
            }
            ...
        }
Run Code Online (Sandbox Code Playgroud)

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