JavaFX PropertyValueFactory 无法从位于不同包中的类接收属性

And*_*eak 1 java javafx package

我有两个包,一个用于对象,另一个用于创建 GUI。我正在尝试TableView在 JavaFX 中创建一个,我必须使用它PropertyValuesFactory<>(property)来获取对象的值。所以我有一个错误,如果我将 Person 和 GUI 类放在同一个包中,一切都会正常工作,但是当 Person 类放在对象包中时,一切都会变糟,我收到此错误:

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
Run Code Online (Sandbox Code Playgroud)

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

person_column.setCellValueFactory(new PropertyValueFactory<>("name"));
Run Code Online (Sandbox Code Playgroud)

因此,我认为可能必须更改财产价值位置...我将不胜感激。

Sla*_*law 5

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

文档PropertyValueFactory提到,你需要做的,如果在部署应用程序作为一个模块的内容:

将应用程序部署为模块

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

例如,如果Person类在模块的com.foo包中foo.app,则module-info.java可能如下所示:

module foo.app {
    opens com.foo to javafx.base;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果模块无条件导出包含的包,则类可以反射访问


另一种选择是放弃PropertyValueFactory并使用自定义Callback. PropertyValueFactory当 lambdas 不是一个东西时,这更方便;在 lambdas 之前,如果想使用 custom Callback,则每次都必须创建一个匿名类,这是冗长的。然而,由于 lambdas,人们可以这样做:

person_column.setCellValueFactory(features -> features.getValue().nameProperty());
Run Code Online (Sandbox Code Playgroud)

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