问题描述
我正在尝试创建一个自定义JavaFX元素以在FXML中使用,但是当FXMLLoader
试图对其进行解析时,它会抛出一个异常,指出:
I am trying to create a custom JavaFX element for use in FXML, but when FXMLLoader
tries to parse it, it throws an exception that states:
但是,在进行了一些研究之后,我相信我正在正确定义默认属性.
However, after doing some research, I believe that I am defining the default property properly.
如果我包含nestedCellValueFactory
标记,则一切正常.
If I include the nestedCellValueFactory
tags, everything works as expected.
@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>
推荐答案
经过一些调试,我对该错误有可能的解释,但遗憾的是没有解决方案.
After some debugging, I have a possible explanation for the error, but sadly not a solution for it.
如果您运行时没有<nestedCellValueFactory>
标记(如您已经报告的那样),则会出现此异常:
If you run without the <nestedCellValueFactory>
tags, as you already reported, you will get this exception:
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
源以跟踪异常,您将找到:
So going to the FXMLLoader
sources to track the exception you will find:
-
第790行:
parent.set(value);
,其中parent
是FXMLLoader$InstanceDeclarationElement
的实例,类型为<your.package.name>. NestablePropertyValueFactory
,而value
是PropertyValueFactory
对象.
Line 790:
parent.set(value);
, whereparent
is an instance ofFXMLLoader$InstanceDeclarationElement
, with type<your.package.name>. NestablePropertyValueFactory
, andvalue
is aPropertyValueFactory
object.
第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
应该为空.
One could expect that defaultProperty.value()
should be "nestedCellValueFactory"
, and the value will be assigned, but the exception thrown clearly shows that this is not the case, so defaultProperty
should be null.
发生什么情况可以通过检查Class<?> type
来解释:
What happens can be explained by inspecting Class<?> type
:
type: class com.sun.javafx.fxml.builder.ProxyBuilder
所以type
不是您的NestablePropertyValueFactory
类,而是一个ProxyBuilder
.
So type
is not your NestablePropertyValueFactory
class, but a ProxyBuilder
.
现在,如果您检查该类,则没有@DefaultProperty
批注,因此defaultProperty
为null并引发异常.
Now, if you check that class there is no @DefaultProperty
annotation, hence defaultProperty
is null and the exception is thrown.
此代理根据实际类型在javafx.fxml.JavaFXBuilderFactory::getBuilder
中创建:
This proxy is created in javafx.fxml.JavaFXBuilderFactory::getBuilder
, based on the real type:
if (scanForConstructorAnnotations(type)) {
builder = new ProxyBuilder(type);
}
,但它会返回ProxyBuilder
,并且在此过程中,DefaultProperty
批注会丢失.
but it returns the ProxyBuilder
instead, and in the process the DefaultProperty
annotation gets lost.
代理构建器似乎旨在用于带有以@NamedArg
注释的构造函数的类,但是对于@DefaultProperty
注释的不是的类.
The proxy builder seems intended for classes with constructors annotated with @NamedArg
, but not for the @DefaultProperty
annotation.
虽然在您的课堂上可能是这种情况,但应该比简短的异常消息更好的解释.
While this could be the case of your class, there should be a better explanation than the short exception message.
无论如何,由于构建器在添加标签并删除默认注释时工作正常,所以我只考虑删除@DefaultProperty
.
Anyway, as the builder works fine when you add the tags and remove the default annotation, I would just consider removing @DefaultProperty
.
这篇关于“元素未定义默认属性";使用@DefaultProperty时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!