【问题标题】:Javafx tableview reflection not workingJavafx tableview反射不起作用
【发布时间】:2017-03-28 06:31:45
【问题描述】:

我正在尝试用模拟数据填充 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

但无论我检查多少,我似乎都找不到我的命名哪里出错了。我错过了什么吗?

我得到的例外是:

线程“JavaFX 应用程序线程”中的异常 java.lang.RuntimeException:java.lang.IllegalAccessException:类 sun.reflect.misc.Trampoline 无法访问带有修饰符“public”的 SensorTableEntry 类的成员 在 com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:200)

【问题讨论】:

  • 尝试将您的 bean 类 SensorTableEntry 转换为 public 类而不是包保护
  • 成功了,谢谢!我知道我犯了一些愚蠢的错误

标签: java javafx


【解决方案1】:

由于您在模型中使用 JavaFX 属性,因此您可以使用回调的实际实现(为简洁起见,使用 lambda 表达式)并完全避免反射。请注意,IntegerProperty 实现了Property&lt;Number&gt;,而不是Property&lt;Integer&gt;,因此您需要修复类型(请参阅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...
}

【讨论】:

  • 这也行得通,但我不得不像这样改变它:TableColumn("ID"); idCol.setCellValueFactory(cellData -> new SimpleIntegerProperty(cellData.getValue().idProperty().getValue()).asObject());
  • @FedericoOrquera 如果您使列可编辑,那将无法正常工作(即使不是,继续创建这样的新属性也是低效的)。正如我在答案中指出的那样,您应该将列的类型从Integer 更改为Number。再次,请参阅stackoverflow.com/questions/24889638/…
【解决方案2】:

您的属性必须是完全可访问的,因此它们的 getter 和它们的所有者类必须都是公开的

所以简单地替换这个:

class SensorTableEntry {

有了这个:

public class SensorTableEntry {

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2018-12-30
    相关资源
    最近更新 更多