Мне действительно нужна помощь.
Я создаю приложение, которое имеет два соединенных поля со списком таким образом, что, если я выбираю 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);
}
});
Фильтрация раскрывающегося списка выполняется с помощью Listener в textProperty () следующим образом:
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, чтобы проверить, выбрано ли значение, и заполнить некоторые текстовые поля своими значениями или установить для них значение 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");
}
}
});
Проблемы следующие:
когда я начинаю вводить что-то в любое поле со списком, он фильтрует нормально, и когда я выбираю элемент из раскрывающегося списка, он заполняет второе поле со списком, но первый редактор поля со списком снова получает фокус и снова отображает раскрывающийся список
когда я удаляю запись из поля со списком, он удаляет нормально, но другое значение поля со списком остается (оно не удаляется)
Если вы можете мне помочь, я буду очень признателен. Заранее спасибо.