繁体   English   中英

根据行项目创建CellFactory

[英]Create CellFactory based on row item

我尝试使用ChoiceBoxTableCell创建TableColumn ChoiceBox中的选项是根据与当前行关联的项目动态生成(并随时间变化的)。 我尝试了不同的方法,但似乎没有任何效果。

我想要这样的东西:

private DataProvider dataProvider;
private TableColumn<Phone, String> testColumn;

public void initialize() {
    testColumn.setCellFactory(param, phone -> new ChoiceBoxTableCell<Phone, String>(dataProvicer.get(phone)));
}

哪里:

public interface DataProvider {
    ObservableList<String> get(Phone phone);
}

这是我想要的理想代码,但是正如您所知, setCallFactoryTableColumn<S,T>作为Callback作为函数参数,并且无法在CellFactory访问它。 我可能会做一些肮脏和丑陋的骇客来了解我想要的原因,但我希望有一些不错的解决方案。

提醒基本机制:cellFactory用于为给定列创建任何的单元格。 调用代码(即表皮肤的实现内部深处的VirtualFlow)不感兴趣,或者不知道为该单元格创建哪一行。 而且,它会被重复使用-设置新项目-经常。 总之,创建单元的时机并不是用行相关数据配置单元的正确时机。 一旦知道该行,就必须在以后完成:最明显的候选对象是updateItem(T, boolean)

现在回到具体的ChoiceBoxTableCell:不幸的是,它的实现太笨了,根本不支持其选择项的动态更新。 因此,您需要一个自定义扩展,它支持动态。 好的一面:ChoiceBoxTableCell公开其项目,从而允许根据需要更改其内容。

如代码注释中所述,事实证明,明显的钩子效果不佳。 因此必须将配置移到startEdit方法中。

一些代码:

public interface ChoiceItemProvider<S, T> {
    ObservableList<T> getItems(S source);
}

public class DynamicChoiceBoxTableCell<S, T> extends ChoiceBoxTableCell<S, T> {

    private ChoiceItemProvider<S, T> provider;

    public DynamicChoiceBoxTableCell(ChoiceItemProvider<S, T> provider) {
        super();
        this.provider = provider;
    }


    /**
     * Not so obvious hook: overridden to update the items of the 
     * choiceBox.
     */
    @Override
    public void startEdit() {
        super.startEdit();
        updateItems();
    }

    /**
     * Obvious hook: override to update the items of the choiceBox.
     * Not fully working - for some reason, the current item isn't
     * selected after starting the edit.
     */
    @Override
    public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        // updateItems();
    }

    /**
     * Dynamically updates the items to current rowItem. 
     */
    @SuppressWarnings("unchecked")
    protected void updateItems() {
        TableRow<S> tableRow = getTableRow();
        S rowItem = tableRow != null ? tableRow.getItem() : null;
        if (provider == null || rowItem == null) return;
        if (provider != null) {
            getItems().setAll(provider.getItems(rowItem));
        } 
    }
}

附录re:

不理想,因为已经扩展的项目不会被更新

如果需要,可以将choiceBox的项目绑定到提供程序返回的项目,而不是调用setAll(provider.getItems())来做:

Bindings.bindContent(getItems(), provider.getItems());
testColumn.setCellFactory(ChoiceBoxTableCell.forTableCoulmn(<dynamic list>));

这应该工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM