Ошибка PropertyValueFactory на правильном получателе из класса модели - PullRequest
1 голос
/ 28 июня 2019

Я пытаюсь заполнить образец javafx TableView из файла fxml.

это мой метод управления:

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 должно начинаться с Uppercase после get word, но это не решило проблему.

Ответы [ 2 ]

3 голосов
/ 28 июня 2019

Хотя нарушение правил именования Java (следуйте им, всегда!) И ненадлежащее использование PropertyValueFactory (не используйте его, если нет веских причин!) Являются обычными подозреваемыми, они, как представляется, не являются причиной в ОПвопрос.

Сообщение об ошибке указывает, что проблема возникает в модульном контексте:

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

На самом деле, пример отлично работает в немодульном контексте, но завершается неудачно при модульности.И сообщение об ошибке говорит нам точно, что делать: откройте наш модуль (или его части) для отражающего доступа.

Информация о модуле, чтобы открыть полный модуль или отдельные пакеты:

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

 // parts
 module JavaFXTest {
   exports ourpackage;
   opens ourpackage.model;
 }
1 голос
/ 28 июня 2019

это очень хороший пример того, «почему вы должны использовать Callback вместо PropertyValueFactory. В настоящее время я не вижу причин использовать PVF вместо Callback.

Здесь вы можете увидеть один недостаток, который заключается в том, что вы на самом деле не видите, что допустили ошибку кодирования перед запуском приложения. Поскольку PVF работает с отражением, он не найдет соответствующие поля, если вы не объявите их правильно. PVF ожидает Property -es, как вы можете видеть в исключении PropertyRefference необходимо, и ни одно из полей delcared в вашем user классе не является Property es

Его можно использовать таким образом, но вы должны переписать класс user, например:

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

Теперь, поскольку поля являются свойствами, PropertyValueFactory найдет их , но Я не рекомендую использовать его, потому что, как вы можете видеть, это может привести к проблемам, которые вы даже не заметили, прежде чем запустить его.

Так что вместо:

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

использование:

// use java naming conventions (`userId` instead of `UserId`)
userId.setCellValueFactory(data -> data.getValue().userIdProperty().asString()); 
// same here user naming convention
userName.setCellValueFactory(data -> data.getValue().userNameProperty());

Я несколько раз писал в качестве комментариев, но я упомяну это здесь снова, чтобы использовал соглашения об именах java . Как пользователь вместо пользователя и идентификатор пользователя вместо идентификатора пользователя и так далее ...

...