如何用ComboBox填充表格列单元格并观察?

时间:2016-10-28 15:11:44

标签: java javafx observablelist

我的表格视图有2列。第一个具有我的对象的名称,第二个我想要一个包含来自我的对象属性列表的值的ComboBox。

对ComboBox的任何更改都将使用用户选择的列表元素更改其选定的属性。

例如:

| Name          | Choices           |
|---------------|-------------------|
| Object 1 Name | Object 1 ComboBox |
| Object 2 Name | Object 2 ComboBox |

到目前为止,我设法填写了这些名字,但我仍然坚持选择栏。

MyObject Model

public class MyObject {

    // Objects name is the filename
    private File file; 
    // Selection from the ComboBox that is populated with infoList elements
    private SomeInfo selectedInfo; 

    private List<SomeInfo > infoList;

    ... getter/setter

控制器

@FXML
private TableView<MyObject> myObjectTableView;
@FXML
private TableColumn<MyObject, String> myObjectNameTableColumn, myObjectChoicesTableColumn;

private void populateTableView(List<MyObject> myObjectList) {
    ObservableList<MyObject> myObjectObservableList = FXCollections.observableList(myObjectList);
    myObjectTableView.setItems(myObjectObservableList);
    myObjectNameTableColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getFile().getName()));
}

1 个答案:

答案 0 :(得分:1)

myObjectChoicesTableColumn的类型错误。你需要

@FXML
private TableColumn<MyObject, List<SomeInfo>> myObjectChoicesTableColumn ;

然后您的单元格值工厂可以

myObjectChoicesTableColumn.setCellValueFactory(cellData -> 
    new SimpleObjectProperty<>(cellData.getValue().getInfoList()));

并显示一个组合框,您需要一个单元工厂:

myObjectChoicesTableColumn.setCellFactory(col -> {

    ComboBox<SomeInfo> combo ;

    TableCell<MyObject, List<SomeInfo>> cell = new TableCell<MyObject, List<SomeInfo>>() {
        @Override
        protected void updateItem(List<SomeInfo> info, boolean empty) {
            super.updateItem(info, empty);
            if (empty) {
                setGraphic(null);
            } else {
                MyObject rowItem = myObjectTableView.getItems().get(getIndex());
                combo.getItems().setAll(info);
                combo.setValue(rowItem.getSelectedInfo());
                setGraphic(combo);
            }
        }
    };

    combo.valueProperty().addListener((obs, oldValue, newValue) -> 
        myObjectTableView.getItems().get(cell.getIndex()).setSelectedInfo(newValue));

    return cell ;
}

您可能会发现重构模型更加清晰,因此您可以将列表和所选项目包装在新类中:

public class SelectableInfo {
    private final ObservableList<SomeInfo> infoList = FXCollections.observableArrayList() ;

    private SomeInfo selectedInfo ;

    public ObservableList<SomeInfo> getInfoList() {
        return infoList ;
    }

    public SomeInfo getSelectedInfo() {
        return selectedInfo ;
    }

    public void setSelectedInfo(SomeInfo info) {
        selectedInfo = info ;
    }
}

public class MyObject {
    private File file ;
    private SelectableInfo selectableInfo ;

    // getters and setters...
}

然后你会更简单:

@FXML
private TableColumn<MyObject, SelectableInfo> myObjectChoicesTableColumn ;

myObjectChoicesTableColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getSelectableInfo());

myObjectChoicesTableColumn.setCellFactory(col -> {
    ComboBox<SomeInfo> combo = new ComboBox<>();
    TableCell<MyObject, SelectableInfo> cell = new TableCell<MyObject, SelectableInfo>() {
        @Override
        protected void updateItem(SelectableInfo info, boolean empty) {
            super.updateItem(info, empty) ;
            if (empty) {
                setGraphic(null);
            } else {
                combo.setItems(info.getInfoList());
                combo.setValue(info.getSelectedInfo());
                setGraphic(combo);
            }
        }
    };
    combo.valueProperty().addListener((obs, oldValue, newValue) -> 
        cell.getItem().setSelectedInfo(newValue));
    return cell ;
});