【问题标题】:How to populate table column cells with ComboBox and observe?如何使用 ComboBox 填充表格列单元格并观察?
【发布时间】:2016-10-28 15:11:43
【问题描述】:

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

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

例如:

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

到目前为止,我已经设法填充了名称,但我被选择列卡住了。

MyObject 模型

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

【问题讨论】:

    标签: java javafx observablelist


    【解决方案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 ;
    });
    

    【讨论】:

    • 不客气。请参阅更新以了解略有不同的方法。
    • James 我不明白如何填充 infoList,因为您的新示例中没有设置器。你错过了还是我错过了什么? :) (可选择的选项是从另一种方法动态给出的)
    • @pror21 你错过了明显的:getSelectableInfo().getInfoList().add(...)getSelectableInfo().getInfoList().addAll(...)getSelectableInfo().getInfoList().setAll(...) 等等(remove(...)clear(),...)。该列表是最终的,不可修改。
    • 哦,你是对的。看来我必须休息一下了。再次感谢您所做的一切!
    猜你喜欢
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 2010-12-17
    相关资源
    最近更新 更多