【问题标题】:Binding nested object properties to TableView in JavaFx在 JavaFx 中将嵌套对象属性绑定到 TableView
【发布时间】:2014-07-15 22:32:14
【问题描述】:

我还有下一堂课

public class ProductStockDto extends 

    private Long id;
    private Long amount;
    private ProductDto product;
    private StockDto stock;

    //getters and setters...
}

在 JavaFx 中,我有我的表,我想将 product.name 属性绑定到列,就像这样。

ObservableList<ProductStockDto> data = FXCollections.observableArrayList();
data.addAll(products);
nameColumn.setCellValueFactory(new PropertyValueFactory("product.name"));
productTable.setItems(data);

但是当我这样做时,TableView 上的行显示为空白。

有人可以帮我解决这个问题吗?我想绑定嵌套对象属性,在 Java Swing 上类似于 ${product.name}

谢谢。

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    作为变体,您可以使用合成属性。

    让我们将其命名为“产品名称”:

    nameColumn.setCellValueFactory(new PropertyValueFactory("productName"));
    

    在您的 ProductStockDto 类中有这样的内容:

    public String getProductName() {
       return product.getName();
    }
    

    【讨论】:

    • 由于某种原因,它给了我一个错误“在类栏中找不到属性 foo 的设置器”。我通过在 getProductName() 函数上方添加 @Transient 注释来解决它。并且还在顶部添加了这个 import javax.persistence.Transient;
    • +1,正确的解决方法。似乎,你有序列化/反序列化,在这种情况下,一对 get/set 是预期的。 Transient 注释将其排除在序列化/反序列化范围之外。
    【解决方案2】:

    我遇到了同样的问题,无法以任何建议的方式使其工作,但是如果我们实例化列并具有嵌套属性(例如,在 Employee 类中)对我有什么影响:

    @FXML
    private TableColumn<Employee, String> columnEmpName;
    @FXML
    private TableColumn<Employee, String> columnEmpLastName;
    @FXML
    private TableColumn<Employee, String> columnEmpJobDesc;
    

    班级是:

    public class Employee {
       private String name;
       private String lastName;
       .
       .
       private EmployeeJobDescription jobDesc; //this one is nested
    }
    

    我已经用我为该属性拾取的字符串制作了ObservableValue&lt;String&gt;

    columnEmpName.setCellValueFactory(new PropertyValueFactory<Employee, String>("name"));
    columnEmpLastName.setCellValueFactory(new PropertyValueFactory<Employee, String>("lastname"));
    columnEmpJobDesc.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getJobDesc().getJobDescription()));
    

    EmployeeJobDescription 将与所有 getter 和 setter 一起使用

    public class EmployeeJobDescription {
    
    private Integer id;
    private String jobDescription;
    
    public EmployeeJobDescription(Integer id) {
        this.id = id;
    }
    
    public EmployeeJobDescription(Integer id, String jobDescription) {
        this.id = id;
        this.jobDescription = jobDescription;
    }
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getJobDescription() {
        return jobDescription;
    }
    
    public void setJobDescription(String jobDescription) {
        this.jobDescription = jobDescription;
    }
    
    }
    

    在这篇文章中了解了如何做到这一点:

    Convert a String to an ObservableValue

    【讨论】:

    • 通过.fxml文件构造列的时候可以用这个方法吗?
    • @Stealth Rabbi 抱歉回答有点晚,但自从这篇文章以来我没有使用过 Java。我相信它可以使用,但我不确定。希望你能找到解决办法
    【解决方案3】:

    请尝试使用 Apache BeanUtils 的以下代码。

    public class StringCellValueFactory implements 
      Callback<CellDataFeatures<Object, String>, ObservableValue<String>> {
        private String property;
    
        public StringCellValueFactory(String property) {
            this.property = property;
        }
    
        public ObservableValue<String> call(CellDataFeatures<Object, String> param) {
            Object value = param.getValue();
            String stringValue = null;
            try {
                stringValue = BeanUtils.getNestedProperty(value, property);
            } catch (Exception e) {
                logger.error("Error in StringCellValueFactory", e);
            }
    
            return new SimpleStringProperty(stringValue);
        }
    }
    

    【讨论】:

    • 可以使用 org.apache.commons.beanutils.PropertyUtils 代替 org.apache.commons.beanutils.BeanUtils,如果值为 java.util.Date,任何用户定义的对象,等
    【解决方案4】:

    Javafx 不支持这种格式,作为一种变通方法,您可以尝试以下方法:

    nameColumn.setCellValueFactory(new Callback<CellDataFeatures<ProductStockDto, String>, 
                                                             ObservableValue<String>>() {  
        @Override  
        public ObservableValue<String> call(CellDataFeatures<ProductStockDto, String> data){  
             return data.getValue().getProducts().nameProperty();  
        }  
    });  
    

    ProductDto 的位置

    public class ProductDto{
    
        private StringProperty name = new SimpleStringProperty("Itachi");
    
        public String getName() {
            return name.get();
        }
    
        public void setStreet(String name) {
            this.name.set(name);
        }
    
        public StringProperty nameProperty(){
            return name;
        }
    }
    

    【讨论】:

      【解决方案5】:
      TableColumn<ProductStockDto , String> ProductNameCol = new ProductNameCol ("Product Name");
      
      ProductNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ProductStockDto , String>, ObservableValue<String>>() {
      
          @Override
          public ObservableValue<String> call(TableColumn.CellDataFeatures<ProductStockDto , String> param) {
              return new SimpleObjectProperty<>(param.getValue().ProductDto ().getName());
      
          }
      });
      

      【讨论】:

      • 一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决了问题,那么答案会更有帮助。
      • 简单而有价值的解决方案。
      【解决方案6】:

      无需更改常规 Java 类:

       nameCol.setCellValueFactory(new Callback<CellDataFeatures<ProductDto, String>, ObservableValue<String>>() {
           public ObservableValue<String> call(CellDataFeatures<ProductDto, String> p) {
               return new ReadOnlyObjectWrapper(p.getValue().getCost());
           }
        });
      

      【讨论】:

      • 请以英文发帖!
      • 请用英文发帖!
      • 回答者文本的翻译将是“没有必要更改您的常规 Java 类:”
      【解决方案7】:

      如果你有一个对象和另一个类型为 String 的属性(例如:ProductDto 类中带有整数的数字“productDto_nr”),你可以用 StringProperty 类型解决这个问题。

      nameColumn.setCellValueFactory(new Callback<CellDataFeatures<ProductStockDto, String>, ObservableValue<String>>() {
          @Override
          public ObservableValue<String> call(CellDataFeatures<ProductStockDto, String> data) {
              StringProperty sp = new SimpleStringProperty();
              sp.setValue(String.valueOf(data.getValue().getProduct().getProductDto_nr()));
              return sp;
          }
      });
      

      【讨论】:

        【解决方案8】:

        你可以简单地使用:

        nameColumn.setCellValueFactory(new PropertyValueFactory("product"));
        

        这将使用对象产品中的 toString() 方法。但是,如果您只这样做,您可能会以“ProductDto@abcef123”之类的内容结尾,这是 toString 方法的复杂对象的默认返回。

        然后你可以做的是覆盖 toString 方法:

        @Override
        public String toString(){
            return //Whatever you want to show
        }
        

        我一直坚持这一点,最终找到了这个解决方案。 希望这会有所帮助。

        【讨论】:

          【解决方案9】:

          如果我们有一个不是原始 java 数据类型的属性,因此我们不能通过步骤直接访问它(例如 ProductStockDto.product.name),其中 ProductStockDto 是一个实体,产品是另一个实体,并且产品具有属性字符串名称。 这里。 正如我在之前的回复中回答的那样,我们需要在 TableView 中呈现名称列。

          此外,您可以使用:javafx.beans.property.adapter 包将 javabeans 对象转换为 javafx beans 对象属性。如果你想要更复杂的代码。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-12-17
            • 1970-01-01
            • 2022-07-05
            • 2011-04-17
            • 1970-01-01
            • 2011-08-22
            • 1970-01-01
            相关资源
            最近更新 更多