问题描述
我正在尝试将数据填充到我的 tableview 中,一切看起来都很好,但仍然没有显示数据。 这是代码。一切似乎都很好,但 tableview 没有显示任何内容。连眨眼都不眨...
public class MainPage implements Initializable {
@FXML
private AnchorPane root;
@FXML
private Button main_logout;
@FXML
private ComboBox<?> main_Clients;
@FXML
private ComboBox<?> main_Users;
@FXML
private TableView<customerDetails> table;
@FXML
private TableColumn<customerDetails,String> clientId;
@FXML
private TableColumn<customerDetails,String> clientName;
@FXML
private TableColumn<customerDetails,String> clientEmail;
@FXML
private TableColumn<customerDetails,String> clientRequirement;
@SuppressWarnings("unchecked")
@Override
public void initialize(URL arg0,ResourceBundle arg1) {
// Todo Auto-generated method stub
clientId.setCellValueFactory(new PropertyValueFactory<customerDetails,String> ("Id"));
clientName.setCellValueFactory(new PropertyValueFactory<customerDetails,String>("name"));
clientEmail.setCellValueFactory(new PropertyValueFactory<customerDetails,String>("email"));
clientRequirement.setCellValueFactory(new PropertyValueFactory<customerDetails,String>("Requirements"));
table=new TableView<customerDetails>();
table.setItems(getClients());
table.getColumns().addAll(clientId,clientName,clientEmail,clientRequirement);
}
@FXML
void loadScene(ActionEvent event) throws IOException
{
AnchorPane pane=FXMLLoader.load(getClass().getResource("/lists/MainPage.fxml"));
root.getChildren().setAll(pane);
}
public ObservableList<customerDetails> getClients()
{
ObservableList<customerDetails> cd=FXCollections.observableArrayList();
customerDetails details=new customerDetails("moin123","moeen","789987","asdf","email","developer","abcd","adsadasdf","78987");
cd.add(details);
return cd;
}
和客户模型..... 我不知道 getter setter 是否有任何问题。我读过一些时候,PropertyValueFactory 存在问题。但在这里,我希望得到一点帮助。
public class customerDetails implements Serializable{
private String Id;
private String name;
private String phone_Number;
private String current_Address;
private String job_Title;
private String Company;
private String Requirements;
private String annual_Salary;
private String email;
public customerDetails()
{
}
public customerDetails(String c_id,String Name,String number,String curr_Add,String j_Title,String company,String req,String salary,String e_mail)
{
this.Id=c_id;
this.name=Name;
this.phone_Number=number;
this.current_Address=curr_Add;
this.job_Title=j_Title;
this.Company=company;
this.Requirements=req;
this.annual_Salary=salary;
this.email=e_mail;
}
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone_Number() {
return phone_Number;
}
public void setPhone_Number(String phone_Number) {
this.phone_Number = phone_Number;
}
public String getCurrent_Address() {
return current_Address;
}
public void setCurrent_Address(String current_Address) {
this.current_Address = current_Address;
}
public String getJob_Title() {
return job_Title;
}
public void setJob_Title(String job_Title) {
this.job_Title = job_Title;
}
public String getCompany() {
return Company;
}
public void setCompany(String company) {
Company = company;
}
public String getRequirements() {
return Requirements;
}
public void setRequirements(String requirements) {
Requirements = requirements;
}
public String getAnnual_Salary() {
return annual_Salary;
}
public void setAnnual_Salary(String annual_Salary) {
this.annual_Salary = annual_Salary;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
知道这里出了什么问题吗?
解决方法
不要使用 PropertyValueFactory。
如您所见,它依赖于反射。这意味着您必须非常小心地指定正确的字符串,因为编译器无法为您验证。
一个更好的主意是避免反射,这样编译器可以验证您是否正确拼写了所有内容。
看看the methods of the Node class。请注意,对于每个 get 方法,如何都有一个返回 JavaFX 属性本身的相应方法?这是 JavaFX 中大多数类中的模式。
例如,有 getBlendMode()
和 blendModeProperty()
方法。 getClip()
和 clipProperty()
方法。 getLayoutX()
和 layoutXProperty()
方法。
您的数据类需要遵循相同的约定:
private final StringProperty idProperty = new SimpleStringProperty();
private final StringProperty nameProperty = new SimpleStringProperty();
public String getId() {
return idProperty.get();
}
public void setId(String id) {
idProperty.set(id);
}
public StringProperty idProperty() {
return idProperty;
}
public String getName() {
return nameProperty.get();
}
public void setName(String name) {
nameProperty.set(name);
}
public StringProperty nameProperty() {
return nameProperty;
}
// etc.
为什么要这样做?因为现在你可以直接向每列的 setCellValueFactory 方法传递一个属性:
clientId.setCellValueFactory(f -> f.getValue().idProperty());
clientName.setCellValueFactory(f -> f.getValue().nameProperty());
// etc.
请注意,上面的代码中没有 "
字符。因为正在使用实际方法,编译器可以确保您没有犯任何错误。 (避免反射还有其他优点,比如性能。)
然而…… 正如 Sedrick 指出的那样,这意味着您的类不会真正可序列化。尝试将其写入 ObjectOutputStream 将导致 NotSerializableException,因为 JavaFX 属性本身不可序列化。我不清楚您是否真的打算序列化 customerDetails 实例;如果是这样,就需要做更多的工作来实现这一点。
至于你的原始代码出了什么问题......
在代码中创建一个新的 TableView
当您加载 MainPage.fxml 时,您的 table
字段将被更改,因此它指向该 .fxml 文件中定义的 TableView。这就是您在窗口中看到的 TableView。
但是你的代码会这样做:
table=new TableView<customerDetails>();
通过这样做,您创建了一个不同的 TableView,它在窗口中根本不可见。您正在设置无人见过的 TableView 项目。
解决方案:完全删除上面的代码行。
属性名称不正确
传递给 PropertyValueFactory 的字符串必须是 bean 属性 名称。 Java bean 也称为 POJO 或普通旧 Java 对象。
Java Bean 规范将 bean 属性定义为获取方法。 bean 的名称定义为 get-method 的名称,不带 get
前缀,和小写的下一个字母。
由于您的 customerDetails 类具有 getId
方法,因此相应 bean 属性的名称为 id
。请注意,一旦删除了“get”,首字母就会变成小写。这很关键。 Bean 属性区分大小写。
当您的代码执行 new PropertyValueFactory<customerDetails,String>("Id")
时,您传递的是一个不存在的属性。 customerDetails 类没有名为“Id”的属性,因此值工厂不可能返回任何数据。但是,该类确实有一个名为“id”的属性。大小写很重要:“id”正确,“Id”不正确。
编译器编译代码,但不执行它。因此编译器不知道该字符串与 customerDetails 中任何 bean 属性的名称都不匹配。这就是为什么反射是危险的。使用编译器可以验证的代码更安全、更健壮。