Data binding 如何创建具有动态列数的表

Data binding 如何创建具有动态列数的表,data-binding,tableview,javafx-2,Data Binding,Tableview,Javafx 2,Thare是一个位于javaFX文档页面的页面。本例描述了如果您有一些sertain java类,如何创建tableView,该类可以告诉您将拥有哪些列。(在本例中是Person类) 但是,如果我没有任何特定的类,并且列的数量可以随时变化,该怎么办? 就我而言,我有这样的数据结构: class TableData{ List<Row> rows; //A list with all my rows i need to have in my table } class Ro

Thare是一个位于javaFX文档页面的页面。本例描述了如果您有一些sertain java类,如何创建tableView,该类可以告诉您将拥有哪些列。(在本例中是Person类)

但是,如果我没有任何特定的类,并且列的数量可以随时变化,该怎么办? 就我而言,我有这样的数据结构:

class TableData{ 
    List<Row> rows; //A list with all my rows i need to have in my table
}

class Row{
    List<Column> columns; //Cells\Columns for every row. 
}

class Column{
    Attribute attr; //Each column - is somethig like a wrapper for the real data i need to show in a cell;
}

class Attribute{ //My precues data
    String name;
    SupportingInfo info;
}

class SupportingInfo{//Some supporting fields...
    String name;
    String value;
    //...etc....
}
类表数据{
列出行;//一个包含我需要在表中包含的所有行的列表
}
班级排{
列出列;//每行的单元格\列。
}
类列{
属性attr;//每列-都像是我需要在单元格中显示的真实数据的包装器;
}
类属性{//My precues data
字符串名;
支持信息化;
}
类支持信息{//某些支持字段。。。
字符串名;
字符串值;
//……等等。。。。
}
所以,我的情况和我的非常相似。 唯一不同的是,上面案例中的数据没有与javaFX表中的表示绑定(因此,即使有人会在tableView中进行额外的控件来编辑此数据,具有该数据的实际对象也永远不会知道它),因为它(数据)像一些字符串一样进入表中,而不像一些对象

所以,我需要的是将数据推送到表中(如:table.setItems(tableData)),设置一些集合工厂,让用户能够编辑数据,并将这些编辑后的数据保存在我的tableData对象中

以下是我为实现这一目的而编写的一些代码:

//prepare my table
private void createTableHeader(TableView table, List<Attribute> ias) {
    int i = 0;
    for (final Attribute ia : ias) {
        final int j = i;
        i++;
        TableColumn tc = new TableColumn(ia.getName());
        tc.setSortable(true);
        tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(CellDataFeatures<List<Attribute>, String> arg0) {
                if(arg0.getValue().get(j).getSupportingInfo() == null){
                    arg0.getValue().get(j).setSupportingInfo(new SupportingInfo());
                }
                return new SimpleObjectProperty(arg0.getValue().get(j),"value");
            }
        });
        table.getColumns().add(tc);
    }
}

//loading some data to my tableView
private void createTableBody(TableView curTable, List<Row> rows) {  
    ObservableList<List<Attribute>> data = FXCollections.observableArrayList();
    for (Row row : rows) {
        data.add(row.getColumns());
    }
    curTable.setItems(data);
}   

//this one is to define some extra controls for editing data in a table by users
private void makeCellFactory(TableColumn curTableCol, final Attribute templateIa, final Document doc) {
    curTableCol.setCellFactory(new Callback<TableColumn, TableCell>() {
        public TableCell call(TableColumn p) {
            final EditingCell cell = new EditingCell(templateIa, doc);
            return cell;
        }
    });
}       
//准备我的表格
私有void createTableHeader(表视图表,列表ias){
int i=0;
for(最终属性ia:ias){
最终int j=i;
i++;
TableColumn tc=新的TableColumn(ia.getName());
tc.可设置可编程(真);
tc.setCellValueFactory(新回调(){
@凌驾
公共ObservableValue调用(CellDataFeatures arg0){
if(arg0.getValue().get(j.getSupportingInfo()==null){
arg0.getValue().get(j).setSupportingInfo(新的SupportingInfo());
}
返回新的SimpleObject属性(arg0.getValue().get(j),“value”);
}
});
table.getColumns().add(tc);
}
}
//将一些数据加载到我的tableView
私有void createTableBody(TableView可压缩,列表行){
ObservableList data=FXCollections.observableArrayList();
用于(行:行){
data.add(row.getColumns());
}
可缩减。设置项(数据);
}   
//这是定义一些额外的控件,用于用户编辑表中的数据
私有void makeCellFactory(TableColumn curTableCol、最终属性templateIa、最终文档文档){
curTableCol.setCellFactory(新回调(){
公共TableCell调用(TableP列){
最终编辑单元=新编辑单元(模板、文档);
返回单元;
}
});
}       
但是,结果是,我的表中只有空行,可以单击某些单元格并接收表编辑控件。但by表中没有默认值; 我的代码哪里做错了?

好的,我找到了一个解决方案: ts.setCellFactory应如下所示:

tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, SupportingInfo>, ObservableValue<Attribute>>() {
 @Override
 public ObservableValue<Attribute> call(CellDataFeatures<List<Attribute>, SupportingInfo> arg0) {
  return new SimpleObjectProperty(arg0.getValue().get(j),"value",arg0.getValue().get(j));
 }
});
tc.setCellValueFactory(新回调(){
@凌驾
公共ObservableValue调用(CellDataFeatures arg0){
返回新的SimpleObject属性(arg0.getValue().get(j),“value”,arg0.getValue().get(j));
}
});
此外,捕获新值并将传入数据放入表中需要此代码:

tc.setOnEditCommit(new EventHandler<CellEditEvent<List<Attribute>, Attribute>>() {
    @Override
    public void handle(CellEditEvent<List<Attribute>, Attribute> t) { t.getTableView().getItems().get(t.getTablePosition().getRow()).get(j).setSupportingInfo(t.getNewValue().getSupportingInfo());
    }
});
tc.setOnEditCommit(新的EventHandler(){
@凌驾
公共无效句柄(CellEditEvent t){t.getTableView().getItems().get(t.getTablePosition().getRow()).get(j).setSupportingInfo(t.getNewValue().getSupportingInfo());
}
});

我试图将您的代码放入一个类中并进行编译,但没有成功。Row#getColumns应返回右侧列的列表,但在#createTableBody中,它被添加到ObservableList中。也许使用2D属性数组可以简化事情?createTableHeader方法中的表列作为makeCellFactory参数传递?如果是这样的话,就很自然地只期望最后的行为,因为我相信TableColumn只能有一个cellFactory。如果设置两次,最后一个将是有效的