我正在尝试创建用于FXML的自定义JavaFX元素,但是当FXMLLoader
试图解析它时,它会抛出一个异常,指出:
javafx.fxml.LoadException:元素未定义默认属性。
但是,在进行了一些研究之后,我相信我正在正确定义默认属性。
如果我包含nestedCellValueFactory
标记,则一切正常。
爪哇
@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);
}
}
XML文件
<NestablePropertyValueFactory property="outer">
<NestablePropertyValueFactory property="inner">
<PropertyValueFactory property="property"/>
</NestablePropertyValueFactory>
</NestablePropertyValueFactory>
最佳答案
经过一些调试后,我有一个可能的错误解释,但遗憾的是没有解决方案。
如果您没有报告<nestedCellValueFactory>
标记而运行,则将收到此异常:
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);
,其中parent
是FXMLLoader$InstanceDeclarationElement
的实例,类型为<your.package.name>. NestablePropertyValueFactory
,而value
是PropertyValueFactory
对象。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<?> 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
。