本文介绍了JavaFX PropertyValueFactory无法从位于不同包中的类接收属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个软件包,一个用于对象,另一个用于创建GUI.我正在尝试在JavaFX中创建TableView,并且必须使用PropertyValuesFactory<>(property)来获取对象的值.因此,我有一个错误:如果将Person和GUI类放在同一个程序包中,则一切正常,但是将Person类放入对象程序包时,一切都会变坏,并且出现此错误:

I have two packages, one for objects and the other for creating GUI. I am trying to create a TableView in JavaFX and I have to use PropertyValuesFactory<>(property) to get the value of the object. So I have a bug where if I put the Person and GUI class in the same package everything would work for fine, but when the Person class is put in the objects package everything goes bad and I get this error:

WARNING: Can not retrieve property 'name' in PropertyValueFactory: javafx.scene.control.cell.PropertyValueFactory@6771b7fb with provided class type: class uni.rest.objects.Person
    java.lang.RuntimeException: java.lang.IllegalAccessException: module javafx.base cannot access class uni.rest.objects.Person (in module main) because module main does not open uni.rest.objects to javafx.base

这也是发生错误的代码行:

This is also the line of code where the error happens:

person_column.setCellValueFactory(new PropertyValueFactory<>("name"));

因此,我认为可能必须更改属性值的位置...我将不胜感激任何帮助.

So I assume that the property value location might have to be changed...I would appreciate any help.

推荐答案

PropertyValueFactory类使用反射来访问模型类的属性. Java 9中添加的模块系统增加了更大的封装,这可以防止模块反射地访问其他模块,除非得到module-info.java中的指令允许.

The PropertyValueFactory class uses reflection to access the model class' properties. The module system added in Java 9 adds greater encapsulation which prevents modules from reflectively accessing other modules unless given permission by directives in module-info.java.

文档 PropertyValueFactory提到了将应用程序作为模块部署时需要做的事情:

The documentation of PropertyValueFactory mentions what you need to do if deploying your application as a module:

如果引用的类在命名模块中,则javafx.base模块必须可以反射地访问它.如果模块至少将javafx.base模块的包含包打开.否则, call(TableColumn.CellDataFeatures) 方法将记录警告并返回null.

If the referenced class is in a named module, then it must be reflectively accessible to the javafx.base module. A class is reflectively accessible if the module opens the containing package to at least the javafx.base module. Otherwise the call(TableColumn.CellDataFeatures) method will log a warning and return null.

例如,如果Person类位于foo.app模块的com.foo包中,则module-info.java可能看起来像这样:

For example, if the Person class is in the com.foo package in the foo.app module, the module-info.java might look like this:

module foo.app {
    opens com.foo to javafx.base;
}

或者,如果模块无条件导出包含的包

Alternatively, a class is reflectively accessible if the module exports the containing package unconditionally


另一个选择是放弃PropertyValueFactory并使用自定义的Callback.当lambda不是问题时,PropertyValueFactory更为方便.在lambda之前,如果要使用自定义Callback,则每次必须创建一个冗长的匿名类.由于使用lambda,因此可以做到:


Another option is to forgo PropertyValueFactory and use a custom Callback. The PropertyValueFactory was more of a convenience for when lambdas were not a thing; before lambdas, if one wanted to use a custom Callback, one would have to create an anonymous class each time which was verbose. Since lambdas, however, one can do:

person_column.setCellValueFactory(features -> features.getValue().nameProperty());

很显然,如果模型公开了JavaFX属性,则效果最佳.自定义Callback的优点包括避免反射和类型安全.

Obviously, this works best if the model exposes a JavaFX property. The advantages of a custom Callback include avoidance of reflection and type safety.

这篇关于JavaFX PropertyValueFactory无法从位于不同包中的类接收属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 19:21