来自模型类的正确获取器的PropertyValueFactory错误

时间:2019-06-28 07:58:24

标签: java javafx openjfx

我正在尝试从fxml文件填充示例javafx TableView。

这是我的控制器方法:

public class TestController implements Initializable {


       @FXML private TableView<user> tableView;
        @FXML private TableColumn<user, String> UserId;
        @FXML private TableColumn<user, String> UserName;


        public void initialize(URL location, ResourceBundle resources) {
            UserId.setCellValueFactory(new PropertyValueFactory<user, String>("userId"));
            UserName.setCellValueFactory(new PropertyValueFactory<user, String>("userName"));


            tableView.getItems().setAll(parseUserList());
        }
        private List<user> parseUserList(){

            List<user> l_u = new ArrayList<user>();

            user u = new user();
            u.setUserId(1);
            u.setUserName("test1");
            l_u.add(u);

            u.setUserId(2);
            u.setUserName("test2");
            l_u.add(u);

            u.setUserId(3);
            u.setUserName("test3");
            l_u.add(u);


            return l_u;
        }

}

和fxml文件:

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="369.0" prefWidth="505.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="viewmodel.TestController ">

   <center>
      <TableView fx:id="tableView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
        <columns>
          <TableColumn prefWidth="75.0" text="UserId" fx:id="UserId"/>
          <TableColumn prefWidth="75.0" text="UserName" fx:id="UserName"/>
        </columns>
      </TableView>
   </center>
</BorderPane>

最后是我的模型:

包装型号;

public class user {
    private int userId;

    public int getUserId() { return this.userId; }
    public void setUserId(int userId) { this.userId = userId; }

    private String userName;

    public String getUserName() { return this.userName; }
    public void setUserName(String userName) { this.userName = userName; }
}

现在,当我尝试填充它时,出现此错误:

Jun 28, 2019 12:17:35 PM javafx.scene.control.cell.PropertyValueFactory getCellDataReflectively
WARNING: Can not retrieve property 'userId' in PropertyValueFactory: javafx.scene.control.cell.PropertyValueFactory@638db851 with provided class type: class model.user
java.lang.RuntimeException: java.lang.IllegalAccessException: module javafx.base cannot access class model.user (in module JavaFXTest) because module JavaFXTest does not open model to javafx.base
    at javafx.base/com.sun.javafx.property.PropertyReference.get(PropertyReference.java:176)

关于SO的一些文章提到,getter和setter属性必须在获取单词后以大写字母开头,但这不能解决问题。

2 个答案:

答案 0 :(得分:3)

虽然通常会怀疑是违反Java命名约定(始终遵循它们!)和PropertyValueFactory使用不当(如果没有令人信服的原因,请不要使用它),但这似乎不是OP的原因。题。

错误消息表明该问题在模块化上下文中发生:

Jun 28, 2019 12:17:35 PM javafx.scene.control.cell.PropertyValueFactory getCellDataReflectively
WARNING: Can not retrieve property 'userId' in PropertyValueFactory:   
    javafx.scene.control.cell.PropertyValueFactory@638db851 with provided class type: class model.user
java.lang.RuntimeException: java.lang.IllegalAccessException: 
    module javafx.base cannot access class model.user (in module JavaFXTest) 
    because module JavaFXTest does not open model to javafx.base

实际上,该示例在非模块化上下文中运行得很好,但在模块化时失败。错误消息告诉我们确切的操作:打开模块(或模块的一部分)以进行反射访问。

Module-info打开完整的模块或单个软件包:

 // complete
 open module JavaFXTest {
   exports ourpackage;
   ...
 }

 // parts
 module JavaFXTest {
   exports ourpackage;
   opens ourpackage.model;
 }

答案 1 :(得分:1)

这是“为什么应使用{'data': [ {'id': 1, 'schedule': {'car': 'Honda', 'show_date': '10/18/2017', 'time_available': ['14:45', '17:10'], 'code': 'A'}}, {'id': 3, 'schedule': {'car': 'Honda', 'show_date': '10/18/2017', 'time_available': ['19:35'], 'code': 'C'}}, {'id': 4, 'schedule': {'car': 'Toyota', 'show_date': '10/18/2017', 'time_available': ['12:20', '14:45'], 'code': 'B'}} ]}) 而不是Callback的一个很好的例子。目前,我看不出有任何理由使用PVF代替Callback。

在这里您可以看到一个缺点,那就是您在运行应用程序之前并没有真正看到编码错误。 由于PVF与反射一起使用,因此如果您未正确声明它们,它将找不到合适的字段。如您所见,PVF期望PropertyValueFactory-es Property是必需的,并且 PropertyRefference 类中讲授的所有字段都不是user es

可以通过这种方式使用它,但是您必须像这样重写 Property 类:

user

现在,由于字段是属性,PropertyValueFactory会找到它们,但我不建议使用它,因为正如您所看到的,它可能导致您甚至在运行它之前都没有注意到的问题

所以不是:

public class User { // use java naming conventions 
    private IntegerProperty userId;

    public int getUserId() { return this.userId.get(); }
    public void setUserId(int userId) { this.userId.set(userId); }
    public IntegerProperty userIdProperty() { return this.userId; }

    private StringProperty userName;

    public String getUserName() { return this.userName.get(); }
    public void setUserName(String userName) { this.userName.set(userName); }
    public StringProperty userNameProperty() {return this.userName; }

    public User(int userId,String userName){
         this.userId = new SimpleIntegerProperty(userId);
         this.userName = new SimpleStringProperty(userName);
    }
}

使用:

UserId.setCellValueFactory(new PropertyValueFactory<user, String>("userId"));
UserName.setCellValueFactory(new PropertyValueFactory<user, String>("userName"));

我已经写过几次评论,但是在这里我将再次提及以使用Java命名约定。像User而不是user一样,UserId而不是UserId等等,等等...