-->

更改ITEMLIST从另一个组合框的选择取决于一个ComboBox(Change ItemList

2019-11-03 02:52发布

首先我必须道歉,因为英语不是我的母语,但我会尽量在我问什么我清楚。

我有一组在的tableview行,每一行都有每一列diferent comboboxs。 因此,组合框之间的互动必须是每行。 如果在ComboBox A1,我选择第1项,在下拉列表A2的ITEMLIST将被更新。 我的问题是,每一个组合框A2,B2,C2等是否正在按照A1中的选择... ...与B1,C1的组合框同样的事情更新。 我需要更新的仅仅是A2,根据A1。 根据B1 B2等

我通过cellfactory设置的组合框,因为我不得不从后面的数据保存在一个序列化对象。

希望是明确的。

问候。

Answer 1:

这是非常痛苦......

TableCell ,你可以观察到TableRow通过它的tableRowProperty()

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

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

痛苦的是,这些价值就可以了,会在某个点的变化。 所以,你需要的东西来观察不断变化,你必须管理添加和删除监听器发生这种情况。

该Bindings.select方法应该是帮助管理这样的事情,但是作为JavaFX的8,它打印巨大的堆栈跟踪到输出的警告每当遇到一个空值,它经常做。 因此,我建议,直到固定做你自己的监听器管理。 (出于某种原因,JavaFX的团队似乎并不认为这是一个大问题,即使在一个Bindings.select定义的路径遇到空值在API文档中明确支持。)

这只是为了稍微不愉快时, getTableRow()在方法TableCell<S,T>返回TableRow ,而不是更明显TableRow<S> (有可能是为了这个,我不能明白了一个道理,但是,嗯...)。 所以,你的代码另外被蒙上散落。

我创建了一个例子的作品:它道歉是基于美国的地理位置,但我有很多已经写好的例子。 我真的希望我失去了一些东西,并且有更容易的方法可以做到这一点,请随时提出的东西,如果任何人有更好的想法。

在最后一个音符:在EasyBind库可以提供结合到一起的任意路径属性简单的方法。



Answer 2:

作为@ James_D的例子不再由于链路腐烂运行,而我处理这个同样的问题,这里就是我想通了,要产生这种效果。

这里查看完整的测试用例。

我延长内置ComboBoxTableCell<S, T>以暴露必要的字段。 定制TableCell具有Supplier<S> tableValue = (S) this.getTableRow().getItem(); 用于访问数据适用对象。 此外,我反射性地检索和存储于电池的参考ComboBox 。 因为它是在超懒洋洋地实例化,我也有通过反射来设置它之前,我可以得到它。 最后,我必须初始化ComboBox为好,因为这将是在javafx.scene.control.cell.CellUtils.createComboBox ,因为我手动创建。 它揭露这些人好像是很重要的:

在列的CellFactory,我们完成初始化ComboBoxCell。 我们只需要创建我们自定义的新实例ComboBoxTableCell ,然后当显示首次下拉框中(例如,我们可以肯定的是,我们有与电池相关的数据对象),我们将绑定ComboBox#itemsPropertyBindings.When返回适当ObservableList的情况。

CellFactory:

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

定制ComboBoxTableCell:

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


文章来源: Change ItemList in a ComboBox depending from another ComboBox choice