Combobox 根据其他组合框选项更改组合框中的ItemList

Combobox 根据其他组合框选项更改组合框中的ItemList,combobox,javafx,refresh,tableview,items,Combobox,Javafx,Refresh,Tableview,Items,首先,我必须道歉,因为英语不是我的母语,但我会尽量澄清我的问题 我在tableview中有一组行,每行每列有不同的ComboBox。因此,combobox之间的交互必须是每行。如果在组合框A1中选择项目1,则在组合框A2中,项目列表将更新。 我的问题是,每个组合框A2、B2、C2等都在根据A1中的选择进行更新。。。B1,C1组合框也是一样。 根据A1,我只需要更新A2。B2根据B1等 我通过cellfactory设置组合框,因为我必须将后面的数据保存在可序列化对象中 希望是明确的 问候。这真是一

首先,我必须道歉,因为英语不是我的母语,但我会尽量澄清我的问题

我在tableview中有一组行,每行每列有不同的ComboBox。因此,combobox之间的交互必须是每行。如果在组合框A1中选择项目1,则在组合框A2中,项目列表将更新。 我的问题是,每个组合框A2、B2、C2等都在根据A1中的选择进行更新。。。B1,C1组合框也是一样。 根据A1,我只需要更新A2。B2根据B1等

我通过cellfactory设置组合框,因为我必须将后面的数据保存在可序列化对象中

希望是明确的


问候。

这真是一种痛苦

TableCell
,您可以通过
tableRowProperty()
观察
TableRow

TableRow
,您可以通过表行的
itemProperty()
观察行中的项

当然,从行中的项目中,您可以观察模型类中定义的任何属性,并相应地更新组合框中的项目列表

令人痛苦的是,这些价值观中的任何一个都会在某个时刻发生变化。因此,您需要观察的内容不断变化,并且您必须在这种情况下管理添加和删除侦听器

该方法应该有助于管理这样的事情,但从JavaFX8开始,每当遇到空值时,它就会将大量堆栈跟踪打印到输出中作为警告,这是经常发生的。因此,我建议您自己进行侦听器管理,直到修复为止。(由于某种原因,JavaFX团队似乎不认为这是一个大问题,即使在绑定中定义的路径中遇到空值。API在API文档中是明确支持的)

只是为了让它稍微令人不愉快,
TableCell
中的
getTableRow()
方法返回一个
TableRow
,而不是更明显的
TableRow
。(我看不出这可能有什么原因,但是,嗯…)。因此,您的代码中还充斥着类型转换

我创建了一个有效的示例:抱歉,它基于美国的地理位置,但我已经编写了很多示例。我真的希望我遗漏了一些东西,并且有更简单的方法来做到这一点:如果有人有更好的想法,请随时提出建议


最后一点注意:该库可能提供了一种更简单的方法来沿任意路径绑定属性。

由于@James_D的示例由于链接损坏而不再运行,我正在处理同样的问题,下面是我如何创建这种效果的

我扩展了内置的
ComboBoxTableCell
,以公开必要的字段。自定义的
TableCell
有一个
Supplier tableValue=(S)this.getTableRow().getItem()用于访问适用的数据对象。此外,我还以反射方式检索并存储对单元格的
组合框的引用。因为它是在超类中惰性地实例化的,所以在获得它之前,我还必须通过反射来设置它。最后,我还必须初始化组合框,就像在
javafx.scene.control.cell.CellUtils.createComboBox中一样,因为我是手动创建它的。重要的是要公开这些信息,如:

在列的CellFactory中,我们完成对ComboBoxCell的初始化。我们只需要为自定义的
ComboBoxTableCell
创建一个新实例,然后当comboBox第一次显示时(例如,我们可以确保我们有一个与单元格关联的数据对象),我们将
组合框#itemsProperty
绑定到
绑定。当
返回案例的适当
可观察列表时

细胞工厂:

    column1.setCellFactory(c -> {
        TransparentComboBoxTableCell<Data, Enum> tcbtc = new TransparentComboBoxTableCell<>();
        tcbtc.comboBox.setOnShown(e -> {
            if (!tcbtc.comboBox.itemsProperty().isBound()) tcbtc.comboBox.itemsProperty().bind(
                    Bindings.when(tcbtc.tableValue.get().base.isEqualTo(BASE.EVEN)).then(evens).otherwise(
                    Bindings.when(tcbtc.tableValue.get().base.isEqualTo(BASE.ODD)).then(odds).otherwise(
                    FXCollections.emptyObservableList()
                    ))
            );
        });
        return tcbtc;
    });
column1.setCellFactory(c->{
TransparentCoboxTableCell tcbtc=新的TransparentCoboxTableCell();
tcbtc.comboBox.setOnShown(e->{
如果(!tcbtc.comboBox.itemsProperty().IsBind())tcbtc.comboBox.itemsProperty().bind(
Bindings.when(tcbtc.tableValue.get().base.isEqualTo(base.EVEN)).then(evens)。否则(
Bindings.when(tcbtc.tableValue.get().base.isEqualTo(base.ODD)).then(赔率)。否则(
FXCollections.emptyObservableList()
))
);
});
返回tcbtc;
});
自定义ComboxTableCell:

public static class TransparentComboBoxTableCell<S, T> extends ComboBoxTableCell<S, T> {
    public TransparentComboBoxTableCell() {
        this(FXCollections.observableArrayList());
    }
    public TransparentComboBoxTableCell(ObservableList<T> startingItems) {
        super(startingItems);
        try {
            Field f = ComboBoxTableCell.class.getDeclaredField("comboBox");
            f.setAccessible(true);
            f.set(this, new ComboBox<>());
            comboBox = (ComboBox<T>) f.get(this);
            // Setup out of javafx.scene.control.cell.CellUtils.createComboBox
            // comboBox.converterProperty().bind(converter);
            comboBox.setMaxWidth(Double.MAX_VALUE);
            comboBox.getSelectionModel().selectedItemProperty().addListener((ov, oldValue, newValue) -> {
                if (this.isEditing()) {
                    this.commitEdit((T) newValue);
                }
            });
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
            Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
            throw new Error("Error extracting 'comboBox' from ComboBoxTableCell", ex);
        }
        tableValue = () -> (S) this.getTableRow().getItem();
    }

    public final ComboBox<T> comboBox;
    public final Supplier<S> tableValue;
}
公共静态类transparentComboxTableCell扩展ComboxTableCell{
公共透明ComboxTableCell(){
这(FXCollections.observableArrayList());
}
公共透明BoxTableCell(可观察列表启动项){
超级(启动项目);
试一试{
字段f=ComboBoxTableCell.class.getDeclaredField(“comboBox”);
f、 setAccessible(true);
f、 设置(此,新组合框());
comboBox=(comboBox)f.get(this);
//从javafx.scene.control.cell.CellUtils.createComboBox中设置
//comboBox.converterProperty().bind(转换器);
comboBox.setMaxWidth(Double.MAX_值);
comboBox.getSelectionModel().SelectEditeProperty().addListener((ov、oldValue、newValue)->{
if(this.isEditing()){
这个.committedit((T)newValue);
}
});
}捕获(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex){
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE,null,ex);
抛出新错误(“从ComboBoxTableCell提取“comboBox”时出错”,例如);
}
tableValue=()->(S)this.getTableRow().getItem();
}
公共最终组合框组合框;
公共最终供应商价值;
}