JavaFX PropertyValueFactory unable to receive property from a class located in different packages

问题: 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) t...

问题:

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.


回答1:

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.

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

Deploying an Application as a Module

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.

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


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());

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

  • 发表于 2019-03-16 19:11
  • 阅读 ( 638 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除