我正在尝试使用模拟数据填充JavaFx TableView列,但我仍然遇到反射错误,即使我认为我正确遵循Bean约定:
// Data model
class SensorTableEntry {
SensorTableEntry(Integer id, String man, String type, String addr) {
this.id = new SimpleIntegerProperty(id);
this.manufacturer = new SimpleStringProperty(man);
this.type = new SimpleStringProperty(type);
this.btAddress = new SimpleStringProperty(addr);
}
private IntegerProperty id;
public Integer getId() { return idProperty().get(); }
public void setId(Integer value) { idProperty().set(value); }
public IntegerProperty idProperty() { return id; }
private StringProperty manufacturer;
public void setManufacturer(String value) { manufacturerProperty().set(value); }
public String getManufacturer() { return manufacturerProperty().get(); }
public StringProperty manufacturerProperty() { return manufacturer; }
private StringProperty type;
public void setType(String value) { typeProperty().set(value); }
public String getType() { return typeProperty().get(); }
public StringProperty typeProperty() { return type; }
private StringProperty btAddress;
public void setBtAddress(String value) { btAddressProperty().set(value); }
public String getBtAddress() { return btAddressProperty().get(); }
public StringProperty btAddressProperty() { return btAddress; }
}
// More code before this...
// Actual table inside the controller
ObservableList<SensorTableEntry> sensorEntries = FXCollections.observableArrayList(
new SensorTableEntry(1, "manufacturer", "type", "00:00:00:00:00:00")
);
TableView<SensorTableEntry> table = new TableView<SensorTableEntry>();
TableColumn<SensorTableEntry,Integer> idCol = new TableColumn<SensorTableEntry,Integer>("ID");
idCol.setCellValueFactory(new PropertyValueFactory<SensorTableEntry,Integer>("id"));
TableColumn<SensorTableEntry,String> manufacturerCol = new TableColumn<SensorTableEntry,String>("Manufacturer");
manufacturerCol.setCellValueFactory(new PropertyValueFactory<SensorTableEntry,String>("manufacturer"));
TableColumn<SensorTableEntry,String> typeCol = new TableColumn<SensorTableEntry,String>("Type");
typeCol.setCellValueFactory(new PropertyValueFactory<SensorTableEntry,String>("type"));
TableColumn<SensorTableEntry,String> btAddressCol = new TableColumn<SensorTableEntry,String>("Bluetooth Address");
btAddressCol.setCellValueFactory(new PropertyValueFactory<SensorTableEntry,String>("btAddress"));
table.setItems(sensorEntries);
table.getColumns().addAll(
idCol,
manufacturerCol,
typeCol,
btAddressCol
);
pane.getChildren().add(table);
我已经检查过类似问题的其他答案,如:
Javafx PropertyValueFactory not populating Tableview
JavaFx TableView not filling all required columns
Javafx tableview not showing data in all columns
但无论我检查多少,我似乎都找不到我命名错误的地方。我错过了什么吗?
我得到的例外是:
线程中的异常&#34; JavaFX应用程序线程&#34; java.lang.RuntimeException:java.lang.IllegalAccessException:类sun.reflect.misc.Trampoline无法使用修饰符&#34; public&#34;来访问SensorTableEntry类的成员。 在com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:200)
答案 0 :(得分:4)
您的媒体资源必须完全可以访问,因此他们的获取者及其所有者类必须都是公开的。
所以只需替换它:
class SensorTableEntry {
有了这个:
public class SensorTableEntry {
答案 1 :(得分:1)
由于您在模型中使用JavaFX属性,因此您可以使用回调的实际实现(为简洁起见使用lambda表达式)并完全避免反射。请注意,IntegerProperty
实现了Property<Number>
,而不是Property<Integer>
,因此您需要修复类型(请参阅JavaFX Properties in TableView):
TableColumn<SensorTableEntry,Number> idCol = new TableColumn<SensorTableEntry,Number>("ID");
idCol.setCellValueFactory(cellData -> cellData.getValue().idProperty());
TableColumn<SensorTableEntry,String> manufacturerCol = new TableColumn<SensorTableEntry,String>("Manufacturer");
manufacturerCol.setCellValueFactory(cellData -> cellData.getValue().manufacturerProperty());
TableColumn<SensorTableEntry,String> typeCol = new TableColumn<SensorTableEntry,String>("Type");
typeCol.setCellValueFactory(cellData -> cellData.getValue().typeProperty());
TableColumn<SensorTableEntry,String> btAddressCol = new TableColumn<SensorTableEntry,String>("Bluetooth Address");
btAddressCol.setCellValueFactory(cellData -> cellData.getValue().btAddressProperty());
这通常是一种更好的方法:编译器将检查属性是否存在且类型是否正确,并且由于您不依赖于反射来评估单元格值,因此性能会更好(可能会忽略不计,但仍然如此) ...)。
另外一个:在JavaFX属性模式中,原始包装器属性的方法应该使用基本类型,而不是对象包装器类型,即:
class SensorTableEntry {
SensorTableEntry(int id, String man, String type, String addr) {
this.id = new SimpleIntegerProperty(id);
this.manufacturer = new SimpleStringProperty(man);
this.type = new SimpleStringProperty(type);
this.btAddress = new SimpleStringProperty(addr);
}
private IntegerProperty id;
public int getId() { return idProperty().get(); }
public void setId(int value) { idProperty().set(value); }
public IntegerProperty idProperty() { return id; }
// existing code...
}