为什么每当我从其父 ComboBox 更改所选项目时,子 ComboBox 都会执行双重操作。?

Why does the child ComboBox performs dual action whenever I change the selected item from its parent ComboBox.?

我有这个嵌套的组合框,每当我从父组合框中 select 编辑某些内容时,子组合框中的项目就会发生变化。第一次尝试时,它的表现完全符合我的要求。但是,当我更改父 Combobox 的 selected 值时,子 Combobox 的操作加倍。

例如,当我select编辑子组合框时,它会显示"Me"。但是每当我更改父项然后再次 select 子项时,它会显示 "Me" 两次,这应该只有一次。

这是我的代码。

cdata = ComboBoxCaller.getCityMun("PH-NCR");
cmbCit.setItems(cdata);
cmbCit.setConverter(new StringConverter<City_Municipality>() {
    @Override
    public String toString(City_Municipality object) {
        return object.getCityName();
    }

    @Override
    public City_Municipality fromString(String string) {
        return cmbCit.getItems().stream().filter(ap -> ap.getCityName().equals(string)).findFirst().orElse(null);
    }
});

pdata = ComboBoxCaller.getProvince();
cmbProv.setItems(pdata);
cmbProv.setConverter(new StringConverter<Province>() {
    @Override
    public String toString(Province object) {
        return object.getPname();
    }

    @Override
    public Province fromString(String string) {
        return cmbProv.getItems().stream().filter(ap -> ap.getPname().equals(string)).findFirst().orElse(null);
    }
});

cmbProv.valueProperty().addListener((ObservableValue<? extends Province> obs, Province oldval, Province newval) -> {
    if (newval != null) {
        System.out.println("Selected: " + newval.getPname() + ". ID: " + newval.getPcode());
        prov_nm = newval.getPname();

        // Setting up list of Cities and Municipality
        cdata = ComboBoxCaller.getCityMun(newval.getPcode());
        cmbCit.setItems(cdata);
        cmbCit.setConverter(new StringConverter<City_Municipality>() {
            @Override
            public String toString(City_Municipality object) {
                return object.getCityName();
            }

            @Override
            public City_Municipality fromString(String string) {
                return cmbCit.getItems().stream().filter(ap -> ap.getCityName().equals(string)).findFirst().orElse(null);
            }
        });

        // this is where the bug/error occurs
        cmbCit.valueProperty().addListener((ObservableValue<? extends City_Municipality> option, City_Municipality old, City_Municipality newVal) -> {
            if (newVal != null) {
                city_nm = newVal.getCityName();
                cit_id = newVal.getPkCit();
                System.out.println("City: " + city_nm + " City ID: " + cit_id);
                isDisable(false);   // disable

                //Setting up list of Sub-Municipalities
                smdata = ComboBoxCaller.getSubMun(newVal.getPkCit());
                cmbSubMun.setItems(smdata);
                cmbSubMun.setConverter(new StringConverter<Sub_Municipality>() {
                    @Override
                    public String toString(Sub_Municipality object) {
                        return object.getSub_mun();
                    }

                    @Override
                    public Sub_Municipality fromString(String string) {
                        return cmbSubMun.getItems().stream().filter(ap -> ap.getSub_mun().equals(string)).findFirst().orElse(null);
                    }
                });

                cmbSubMun.valueProperty().addListener((ObservableValue<? extends Sub_Municipality> opt, Sub_Municipality od, Sub_Municipality nw) -> {
                    if (nw != null) {
                        sub_vil = nw.getSub_mun();
                        subMun = nw.getSub_mun();
                    }
                });

                //Setting up list of Subdivisions and Village
                sdata = ComboBoxCaller.getSubVil(newVal.getPkCit());
                cmbSub.setItems(sdata);
                cmbSub.setConverter(new StringConverter<Subdivision_Village>() {
                    @Override
                    public String toString(Subdivision_Village object) {
                        return object.getSub_vil();
                    }

                    @Override
                    public Subdivision_Village fromString(String string) {
                        return cmbSub.getItems().stream().filter(ap -> ap.getSub_vil().equals(string)).findFirst().orElse(null);
                    }
                });

                cmbSub.valueProperty().addListener((ObservableValue<? extends Subdivision_Village> opt, Subdivision_Village od, Subdivision_Village nw) -> {
                    if (nw != null) {
                        sub_vil = nw.getSub_vil();
                    }
                });
            } else {
                isDisable(true);
            }
        });
    }
});

bug/error 发生在 cmbCit,每当我更改 cmbProv 的 selected 值时,cmbCit 的项目都会更改 BUT,每当我 select 来自 cmbCit 的项目时,它会执行两次。

我看到您在另一个侦听器 cmbProv.valueProperty() 中为 cmbCit.valueProperty() 添加了一个侦听器。对这种实现要非常小心,因为它可能会引发问题:在您的情况下,您 select cmbProv 中的项目越多,您为 cmbCit.valueProperty() 收集的侦听器就越多。每次调用 cmbCit.valueProperty() 时都必须删除侦听器,以确保您的过程不会同时执行多次。