【问题标题】:"Element does not define a default property" when @DefaultProperty is used使用 @DefaultProperty 时“元素未定义默认属性”
【发布时间】:2017-04-17 18:57:13
【问题描述】:

我正在尝试创建一个用于 FXML 的自定义 JavaFX 元素,但是当FXMLLoader 尝试解析它时,它会抛出一个异常,指出:

javafx.fxml.LoadException:元素未定义默认属性。

但是,经过一些研究,我相信我正确定义了默认属性。

如果我包含nestedCellValueFactory 标签,一切都会按预期工作。

Java

@DefaultProperty("nestedCellValueFactory")
public class NestablePropertyValueFactory<S, T> extends PropertyValueFactory<S, T> {

    private ObjectProperty<PropertyValueFactory<?, ?>> nestedCellValueFactory;

    public NestablePropertyValueFactory(
            @NamedArg("property") String property,
            @NamedArg("nestedCellValueFactory") PropertyValueFactory<?, ?> nestedCellValueFactory) {
        super(property);
        this.nestedCellValueFactory = new SimpleObjectProperty<>(this, "nestedCellValueFactory", nestedCellValueFactory);
    }

    public final ObjectProperty<PropertyValueFactory<?, ?>> nestedCellValueFactoryProperty() {
        return nestedCellValueFactory;
    }

    public final PropertyValueFactory<?, ?> getNestedCellValueFactory() {
        return nestedCellValueFactoryProperty().get();
    }

    public final void setNestedCellValueFactory(PropertyValueFactory<?, ?> nestedCellValueFactory) {
        nestedCellValueFactoryProperty().set(nestedCellValueFactory);
    }

}

FXML

<NestablePropertyValueFactory property="outer">
    <NestablePropertyValueFactory property="inner">
        <PropertyValueFactory property="property"/>
    </NestablePropertyValueFactory>
</NestablePropertyValueFactory>

【问题讨论】:

  • 另外,我知道 IDE 的建议并不是衡量实现准确性的可靠标准,但 IntellJ 一直建议我删除 元素,因为它是默认属性,所以我必须相信我至少在某些方面是正确的。
  • 我最初使用 JDK 1.8.0_92 运行它,但我切换到 1.8.0_121 并得到了相同的结果。

标签: java javafx fxml


【解决方案1】:

经过一些调试,我对错误有了可能的解释,但遗憾的是没有解决方案。

如果你在没有&lt;nestedCellValueFactory&gt; 标签的情况下运行,正如你已经报告的那样,你会得到这个异常:

Caused by: javafx.fxml.LoadException: Element does not define a default property.
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$Element.set(FXMLLoader.java:180)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:790)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)

所以去FXMLLoader来源跟踪你会发现的异常:

  • 第 790 行:parent.set(value);,其中 parentFXMLLoader$InstanceDeclarationElement 的实例,类型为 &lt;your.package.name&gt;. NestablePropertyValueFactoryvaluePropertyValueFactory 对象。

  • 第 177-183 行:

    public void set(Object value) throws LoadException {
        ...  
        Class<?> type = this.value.getClass();
        DefaultProperty defaultProperty = type.getAnnotation(DefaultProperty.class);
        if (defaultProperty == null) {
            throw constructLoadException("Element does not define a default property.");
        }
    
        getProperties().put(defaultProperty.value(), value);
    }
    

可以预期defaultProperty.value()应该是"nestedCellValueFactory",并且会赋值,但是抛出的异常清楚地表明不是这样,所以defaultProperty应该为null。

检查Class&lt;?&gt; type可以解释发生了什么:

 type: class com.sun.javafx.fxml.builder.ProxyBuilder

所以type 不是你的NestablePropertyValueFactory 类,而是ProxyBuilder

现在,如果您检查该类,则没有 @DefaultProperty 注释,因此 defaultProperty 为 null 并引发异常。

这个代理是在javafx.fxml.JavaFXBuilderFactory::getBuilder创建的,基于真实类型:

    if (scanForConstructorAnnotations(type)) {
        builder = new ProxyBuilder(type);
    }

但它会返回 ProxyBuilder,而在此过程中 DefaultProperty 注释会丢失。

代理构建器似乎适用于带有@NamedArg 注释的构造函数的类,但不是 用于@DefaultProperty 注释的类。

虽然这可能是您的班级的情况,但应该有比简短的异常消息更好的解释。

无论如何,当您添加标签并删除默认注释时,构建器工作正常,我会考虑删除@DefaultProperty

【讨论】:

  • 感谢您非常详细的回复!这完全有道理。我可以忍受指定属性名称 - 我真的很想知道为什么这不起作用,因为我知道我将来可能会再次尝试使用它。再次感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
相关资源
最近更新 更多