设置属性

有多种方法可以在 fxml 中向对象添加数据:

<property> 标签

可以将具有属性名称的标记添加为用于创建实例的元素的子标记。此标记的子项使用 setter 分配给属性或添加到属性的内容(只读列表/映射属性)。

默认属性

可以使用 @DefaultProperty 注释来注释类。在这种情况下,元素可以直接添加为子元素,而不使用具有属性名称的元素。

property="value" 属性

可以使用属性名称作为属性名称并将值作为属性值来指定属性。这与将以下元素添加为标记的子元素具有相同的效果:

<property>
    <String fx:value="value" />
</property>

静态 setter

也可以使用 static setter 设置属性。这些是名为 setProperty 的 static 方法,它将元素作为第一个参数,将值设置为第二个参数。这些方法可以在任何类中进行,并且可以使用 ContainingClass.property 而不是通常的属性名称来使用。

注意: 目前似乎有必要使用相应的静态 getter 方法(即名为 getProperty 的静态方法,将元素作为与静态 setter 相同的类中的参数),除非值类型为 String。

类型强制

以下机制用于在赋值期间获取正确类的对象,例如,以适合 setter 方法的参数类型。

如果类是可分配的,则使用值本身。

否则,该值转换如下

目标类型 使用价值(来源价值 s)
Boolean,boolean Boolean.valueOf(s)
char,Character s.toString.charAt(0)
其他原始类型或包装类型 适用于目标类型的方法,如果 s 是 Number,则 valueOf(s.toString()) 为包装类型,否则
BigInteger BigInteger.valueOf(s.longValue()) 是 s 是 Number,new BigInteger(s.toString()) 否则
BigDecimal BigDecimal.valueOf(s.doubleValue()) 是 s 是 Number,new BigDecimal(s.toString()) 否则
Number Double.valueOf(s.toString()) 如果 s.toString() 包含 .,则 Long.valueOf(s.toString()) 否则
Class Class.forName(s.toString()) 使用当前线程的上下文 ClassLoader 调用而不初始化类
enum valueOf 方法的结果,如果 s 是以小写字母开头的 String,则另外转换为全部大写的 String,由每个大写字母前插入的 _ 分隔。
other targetType 中 static valueOf 方法返回的值,其参数与 s 的类型或该类型的超类相匹配

注意: 此行为没有详细记录,可能会有所变化。

例

public enum Location {
    WASHINGTON_DC,
    LONDON;
}
package fxml.sample;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.beans.DefaultProperty;

@DefaultProperty("items")
public class Sample {
    
    private Location loaction;

    public Location getLoaction() {
        return loaction;
    }

    public void setLoaction(Location loaction) {
        this.loaction = loaction;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
    
    int number;

    private final List<Object> items = new ArrayList<>();

    public List<Object> getItems() {
        return items;
    }
    
    private final Map<String, Object> map = new HashMap<>();

    public Map<String, Object> getMap() {
        return map;
    }
    
    private BigInteger serialNumber;

    public BigInteger getSerialNumber() {
        return serialNumber;
    }

    public void setSerialNumber(BigInteger serialNumber) {
        this.serialNumber = serialNumber;
    }

    @Override
    public String toString() {
        return "Sample{" + "loaction=" + loaction + ", number=" + number + ", items=" + items + ", map=" + map + ", serialNumber=" + serialNumber + '}';
    }
    
}
package fxml.sample;

public class Container {

    public static int getNumber(Sample sample) {
        return sample.number;
    }

    public static void setNumber(Sample sample, int number) {
        sample.number = number;
    }

    private final String value;

    private Container(String value) {
        this.value = value;
    }

    public static Container valueOf(String s) {
        return new Container(s);
    }

    @Override
    public String toString() {
        return "42" + value;
    }

}

打印加载以下 fxml 文件的结果

Sample{loaction=WASHINGTON_DC, number=5, items=[42a, 42b, 42c, 42d, 42e, 42f], map={answer=42, g=9.81, hello=42A, sample=Sample{loaction=null, number=33, items=[], map={}, serialNumber=null}}, serialNumber=4299}
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import fxml.sample.*?>

<Sample xmlns:fx="http://javafx.com/fxml/1" Container.number="5" loaction="washingtonDc">
    
    <!-- set serialNumber property (type coercion) -->
    <serialNumber>
        <Container fx:value="99"/>
    </serialNumber>
    
    <!-- Add elements to default property-->
    <Container fx:value="a"/>
    <Container fx:value="b"/>
    <Container fx:value="c"/>
    <Container fx:value="d"/>
    <Container fx:value="e"/>
    <Container fx:value="f"/>
    
    <!-- fill readonly map property -->
    <map g="9.81">
        <hello>
            <Container fx:value="A"/>
        </hello>
        <answer>
            <Container fx:value=""/>
        </answer>
        <sample>
            <Sample>
                <!-- static setter-->
                <Container.number>
                    <Integer fx:value="33" />
                </Container.number>
            </Sample>
        </sample>
    </map>
</Sample>