Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding nested object properties to TableView in JavaFx

Tags:

java

javafx

I have the next class

public class ProductStockDto extends 

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

    //getters and setters...
}

In JavaFx I have my table and I want to bind the product.name property to the column, something like this.

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

But when I do that, the rows on the TableView appears on blank.

Somebody can help me with this? I want to bind nested object properties, on Java Swing was something like that ${product.name}

Thanks.

like image 778
Jorge Alvarez Avatar asked Jul 15 '14 22:07

Jorge Alvarez


5 Answers

As variant you may work with synthetic property.

Lets name it as 'productName':

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

In your ProductStockDto class have something like this:

public String getProductName() {
   return product.getName();
}
like image 191
Dmytro Maslenko Avatar answered Nov 19 '22 18:11

Dmytro Maslenko


I had the same problem and couldn't make it work in any suggested way, but what did the trick for me, if we instantiate columns and have nested property, for instance, in class Employee:

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

And class is:

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

I have made ObservableValue<String> out of string I picked up for that property

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

And the EmployeeJobDescription would be with all getters and setters

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

}

Found out how to do that in this post:

Convert a String to an ObservableValue

like image 10
Dach0 Avatar answered Nov 19 '22 18:11

Dach0


This format is not supported in Javafx, as a work around, you can try something like this :

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

where ProductDto will have

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;
    }
}
like image 7
ItachiUchiha Avatar answered Nov 19 '22 19:11

ItachiUchiha


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

    }
});
like image 4
kamel2005 Avatar answered Nov 19 '22 19:11

kamel2005


You can simply use :

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

This will use the toString() method from the object product. However, if you do only this, you may end with something like "ProductDto@abcef123" with is the default return of a complex object of the toString method.

What you can do is then override the toString method :

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

I've been stuck with this, and eventually find this solution. Hope this will help.

like image 1
Xema Avatar answered Nov 19 '22 19:11

Xema