Редактируемый ComboBox с пользовательскими объектами переписывает элементы в раскрывающемся списке

У меня есть фильтруемый ComboBox, заполненный пользовательскими объектами Subjekt.

Отфильтрованный список заполняется из базы данных методом SubjektDAO.searchSubjectsByName().

Добавлен слушатель в редактор ComboBox и используется метод cbNazivKupca.show() для автоматического открытия выпадающего списка (который заполняется и отображается), когда я начинаю печатать.

Фильтрация работает нормально (поскольку я набираю список фильтруется), но когда я выбираю элемент из списка (скажем, «Авраам»), меняю его значение в текстовом поле ComboBox (скажем, на «абра») и щелкаю где-нибудь еще (поэтому ComboBox теряет focus) значение «abrah» появляется в раскрывающемся списке, и я теряю исходное значение.

Мне нужно отключить ввод новых значений в список (я мог бы сделать это, установив поле со списком нередактируемым), но у меня есть большая сумма для прокрутки.

Также, если я нажимаю кнопку, чтобы отобразить элементы в списке, и нажимаю первый элемент в строке, он заполняется в текстовом поле, но если я нажимаю второй или какой-либо следующий, мне нужно щелкнуть его дважды (это происходит только один раз).

Я не знаю, как это решить, я новичок в JavaFX и учусь.

Пожалуйста помоги.

try {

    final FilteredList<Subjekt> filteredItems = new FilteredList<>(SubjektDAO.searchSubjectsByName(), p -> true);

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


        cbNazivKupca.show();

        final TextField editor = cbNazivKupca.getEditor();
        final Subjekt selected = cbNazivKupca.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.toString().equals(editor.getText())) {
                filteredItems.setPredicate(item -> {
                    cbNazivKupca.setVisibleRowCount(10);
                    // We return true for any items that contains the
                    // same letters as the input. We use toUpperCase to
                    // avoid case sensitivity.
                    if (item.getSubjekt_naziv().toUpperCase().contains(newValue.toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                });
            }
        });
    });

    cbNazivKupca.setItems(filteredItems);
} catch (SQLException | ClassNotFoundException e) {
    e.printStackTrace();
}


//  rendering of the list of values in ComboBox drop down.
cbNazivKupca.setCellFactory((comboBox) -> {
    return new ListCell<Subjekt>() {
        @Override
        protected void updateItem(Subjekt subjekt, boolean empty) {
            super.updateItem(subjekt, empty);

            if (subjekt == null || empty) {
                setText(null);
            } else {
                setText(subjekt.getSubjekt_naziv());
            }
        }
    };
});

cbNazivKupca.setConverter(new StringConverter<Subjekt>() {
    @Override
    public String toString(Subjekt subjekt) {
        if (subjekt == null) {
            return null;
        } else {
            return subjekt.getSubjekt_naziv();
        }
    }

    @Override
    public Subjekt fromString(String productString)
    {
        if(cbNazivKupca.getValue() != null)
        {
            ((Subjekt)cbNazivKupca.getValue()).setSubjekt_naziv(productString);

            return (Subjekt)cbNazivKupca.getValue();
        }
        return null;

    }

});

EDITED: я сузил источник проблемы до метода cbNazivKupca.setConverter fromString, но я застрял, мне нужно проверить, присутствует ли cbNazivKupca.getValue() в раскрывающемся списке.

EDITED: я тоже пришел к аналогичному решению, но меня смущает следующее: когда я нажимаю кнопку раскрывающегося списка, и элементы отображаются в списке, если я нажимаю первый в списке, он копируется в редактируемую часть, но если я щелкаю любой другой редактор получает курсор и пуст, и если я щелкну его снова, все хорошо, это происходит только один раз.


person Tonči Krstulović-Jelić    schedule 07.08.2016    source источник


Ответы (1)


Метод fromString вашего преобразователя недействителен. Цель это метод заключается в том, чтобы вернуть объект с типом общего параметра типа StringConverter, и ничего больше:

Преобразует предоставленную строку в объект, определенный конкретным преобразователем. Формат строки и тип результирующего объекта определяется конкретным преобразователем.

Таким образом, в этом методе вы не должны получать выбранный элемент и, что еще хуже, вы не должны изменять выбранный элемент, на самом деле это причина изменения элементов в вашем раскрывающемся списке.

Метод fromString используется, когда вы вводите в редакторе ComboBox, а затем нажимаете Enter, чтобы узнать, какой элемент следует выбрать (элемент, который возвращает метод) на основе строки, которую вы ввели в редакторе (входной параметр метода). .

Что вам нужно сделать, так это получить соответствующий экземпляр Subject из элементов ComboBox, например:

@Override
public Subjekt  fromString(String productString) {
    return cbNazivKupca.getItems().stream().filter(item -> productString.equals(item.getSubjekt_naziv())).findFirst().orElse(null);
}

Это вернет первый элемент из элементов в ComboBox, член subjekt_naziv которого совпадает с указанным String или нулевым, если сопоставление невозможно.

person DVarga    schedule 09.08.2016