我在tableview中有一组行,每行每列有不同的组合框。因此,组合框之间的相互作用必须是每行。如果在Combobox A1中,我选择项目1,在Combobox A2中将更新项目列表。 我的问题是每个组合框A2,B2,C2等都是根据A1中的选择进行更新...与B1,C1组合框相同。 根据A1,我需要更新A2。 B2根据B1等
我通过cellfactory设置组合框,因为我必须将数据从后面保存在可序列化的对象中。
希望很清楚。问候。
答案 0 :(得分:1)
这真是一种痛苦......
从TableCell
,您可以通过它TableRow
观察tableRowProperty()
。
从TableRow
,您可以通过表格行itemProperty()
观察行中的项目。
当然,从行中的项目中,您可以观察模型类中定义的任何属性,并相应地更新组合框中的项目列表。
痛苦的部分是这些价值中的任何一个都可以,并且在某些时候会发生变化。因此,您需要观察的事情不断变化,您必须在发生这种情况时管理添加和删除侦听器。
Bindings.select方法应该有助于管理这样的事情,但是从JavaFX 8开始,它会在遇到空值时将输出的巨大堆栈跟踪打印为警告。因此,我建议您自己进行监听器管理,直到修复为止。 (出于某种原因,JavaFX团队似乎并不认为这是一个大问题,即使在API文档中明确支持在Bindings.select中定义的路径中遇到空值。)
只是为了让它更令人不愉快,getTableRow()
中的TableCell<S,T>
方法会返回TableRow
,而不是更明显的TableRow<S>
。 (这可能是我无法看到的原因,但是,好吧......)。所以你的代码还充斥着演员阵容。
我创建了一个有效的example:为它基于美国地理而道歉,但我已经写了很多例子。我真的希望我能错过一些东西,并且有更简单的方法可以做到这一点:如果有人有更好的想法,请随意提出建议。
最后一点:EasyBind库可以提供一种更简单的方法来绑定任意路径上的属性。
答案 1 :(得分:0)
由于@ James_D的例子由于链接腐烂而不再运行,我正在处理同样的问题,这就是我想出来创建这种效果的方法。
我扩展内置ComboBoxTableCell<S, T>
以暴露必要的字段。自定义TableCell
有Supplier<S> tableValue = (S) this.getTableRow().getItem();
用于访问适用的Data对象。另外,我反过来检索并存储对单元格ComboBox
的引用。因为它在超类中被懒惰地实例化,所以在得到它之前我还必须通过反射来设置它。最后,我必须初始化ComboBox
,就像在javafx.scene.control.cell.CellUtils.createComboBox
中一样,因为我手动创建它。公开这些是很重要的,如:
在列的CellFactory中,我们完成了初始化ComboBoxCell。我们只需要创建一个自定义ComboBoxTableCell
的新实例,然后当第一次显示comboBox时(例如我们可以确定我们有一个与该单元关联的Data对象),我们绑定{{ 1}} ComboBox#itemsProperty
为案例返回正确的Bindings.When
。
CellFactory:
ObservableList
自定义ComboBoxTableCell:
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;
});