根据行项创建CellFactory

时间:2015-08-12 07:45:02

标签: java javafx javafx-8

我尝试使用TableColumn创建ChoiceBoxTableCell。此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);
}

这是我希望拥有的理想代码,但正如您所知setCallFactoryCallbackTableColumn<S,T>作为函数参数,没有办法在CellFactory内访问它。我可能会做一些肮脏和丑陋的黑客来得到我想要的东西,但我希望有一个很好的解决方案。

2 个答案:

答案 0 :(得分:3)

提醒基本机制: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));
        } 
    }
}

补遗:

  

不理想,因为项目已经展开时不会更新

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

Bindings.bindContent(getItems(), provider.getItems());

答案 1 :(得分:-1)

testColumn.setCellFactory(ChoiceBoxTableCell.forTableCoulmn(<dynamic list>));

这应该有用。