【问题标题】:JavaFX connected comboboxesJavaFX 连接的组合框
【发布时间】:2017-01-07 09:56:16
【问题描述】:

我真的需要一些帮助。

我正在创建具有两个连接组合框的应用程序,如果我在第二个中选择 productCode,则应该选择 productName。

两个组合框文本字段都可用于搜索目的。

我已经设置了这样的 setCellFactories(用于下拉列表呈现)。

    cbSifra.setCellFactory((comboBox) -> new ListCell<Product>() {
        @Override
        protected void updateItem(Product product, boolean empty) {
            super.updateItem(product, empty);

            if (product == null || empty) {
                setText(null);
            } else {
                setText(product.getProductCode());
            }
        }
    });

cbNaziv.setCellFactory((comboBox) -> new ListCell<Product>() {
        @Override
        protected void updateItem(Product product, boolean empty) {
            super.updateItem(product, empty);

            if (product == null || empty) {
                setText(null);
            } else {
                setText(product.getProductName());
            }
        }
    });

两个组合框都实现了转换器,以便在选中时将数据显示到组合框中。

cbNaziv.setConverter(new StringConverter<Product>() {
        @Override
        public String toString(Product product) {
            if (product == null) {
                return null;
            } else {
                return product.productNameProperty().get();
            }
        }

        @Override
        public Product fromString(String productString)
        {
            return cbNaziv.getItems().stream().filter(item->productString.equals(item.getProductName())).findFirst().orElse(null);

        }
    });


    cbSifra.setConverter(new StringConverter<Product>() {
        @Override
        public String toString(Product product) {
            if (product == null) {
                return null;
            } else {
                return product.productCodeProperty().get();
            }
        }

        @Override
        public Product fromString(String productString)
        {
            return cbSifra.getItems().stream().filter(item ->productString.equals(item.getProductCode())).findAny().orElse(null);
        }
    });

下拉列表的过滤是在 textProperty() 上使用 Listener 完成的,如下所示:

cbNaziv.getEditor().textProperty().addListener((obs, oldValue, newValue) -> {


                cbNaziv.show();

                final TextField editor = cbNaziv.getEditor();
                final Product selected = cbNaziv.getSelectionModel().getSelectedItem();

        /*
        This needs run on the GUI thread to avoid the error described
        here: https://bugs.openjdk.java.net/browse/JDK-8081700.
        */

                Platform.runLater(() -> {

            /*
            If the no item in the list is selected or the selected item
            isn't equal to the current input, we refilter the list.
            */
                    if (selected == null || !selected.equals(editor.getText())) {
                        filteredProductList.setPredicate(item -> {
                            // We return true for any items that contains the
                            // same letters as the input. We use toUpperCase to
                            // avoid case sensitivity.

                            if (item.getProductName().toUpperCase().contains(newValue.toUpperCase())) {
                                return true;
                            } else {
                                return false;
                            }
                        });
                    }
                });
            });



            cbSifra.getEditor().textProperty().addListener((obs, oldValue, newValue) -> {


                cbSifra.show(); // Is used to open dropdown list as i start typing

                final TextField editor = cbSifra.getEditor();
                final Product selected = cbSifra.getSelectionModel().getSelectedItem();

        /*
        This needs run on the GUI thread to avoid the error described
        here: https://bugs.openjdk.java.net/browse/JDK-8081700.
        */

                Platform.runLater(() -> {

            /*
            If the no item in the list is selected or the selected item
            isn't equal to the current input, we refilter the list.
            */

                    if (selected == null || !selected.equals(editor.getText())) {

                        filteredProductList.setPredicate(item -> {
                            // We return true for any items that contains the
                            // same letters as the input. We use toUpperCase to
                            // avoid case sensitivity.

                            if (item.getProductCode().toUpperCase().contains(newValue.toUpperCase())) {
                                return true;
                            } else {
                                return false;
                            }

                        });
                    }
                });
            });

我有 valueProperty 侦听器来检查是否选择了 value 并将一些 textFields 填充到它们的值或将它们设置为 null。

cbSifra.valueProperty().addListener(new ChangeListener<Product>() {
            @Override
            public void changed(ObservableValue<? extends Product> observable, Product oldValue, Product newValue) {

                if (cbSifra.getValue() == null || cbSifra.getValue().getProductName().isEmpty())
                {
                    cbNaziv.getSelectionModel().clearSelection();
                    tfMpCijena.setText(null);
                    tfPopust.setText(null);

                } else {


                    cbNaziv.setValue(cbSifra.getValue());
                    cbSifra.setValue(cbNaziv.getValue());
                    cbNaziv.hide();
                    tfMpCijena.setText(cbSifra.getValue().getProductRetailPrice().toString());
                    tfPopust.setText("0");
                }

            }
        });



        cbNaziv.valueProperty().addListener(new ChangeListener<Product>() {
            @Override
            public void changed(ObservableValue<? extends Product> observable, Product oldValue, Product newValue) {

                if (cbNaziv.getValue() == null || cbNaziv.getValue().getProductName().isEmpty())
                {
                    cbSifra.getSelectionModel().clearSelection();
                    tfMpCijena.setText(null);
                    tfPopust.setText(null);

                } else {

                    cbSifra.setValue(cbNaziv.getValue());
                    cbSifra.hide();
                    tfMpCijena.setText(cbNaziv.getValue().getProductRetailPrice().toString());
                    tfPopust.setText("0");
                }

            }
        });

问题是:

  • 当我开始在任何组合框中输入内容时,它会过滤正常并且 当我从下拉列表中选择项目时,它会填充第二个组合框,但是 第一个组合框编辑器再次获得焦点并显示下拉菜单 再次

  • 当我从组合框中删除条目时,它会删除,但另一个 组合框值保留(未删除)

如果您能帮助我,我将不胜感激。 提前致谢。

【问题讨论】:

    标签: javafx combobox listeners


    【解决方案1】:

    假设两个 ComboBox 都是 Product 类型,您可以使用双向绑定来确保两个 ComboBox 的值始终指向同一个产品。

    cbNaziv.valueProperty().bindBidirectional(cbSifra.valueProperty());
    

    使用它应该允许您删除更改侦听器,并有望解决您遇到的一些问题。

    【讨论】:

      猜你喜欢
      • 2020-07-16
      • 1970-01-01
      • 2013-06-16
      • 2019-08-23
      • 2017-02-08
      • 2015-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多