JavaFX - Как добавить фильтр автозаполнения для недоступного для редактирования ComboBox - PullRequest
0 голосов
/ 06 мая 2020

У меня два ComboBox. В первый ComboBox я добавляю доступных клиентов из базы данных. Я добавляю список во второй ComboBox на основе выбора первого ComboBox. Я хочу, чтобы ComboBox не редактировался, я показываю текст, набранный во всплывающей подсказке над ComboBox. На основе набранных символов ComboBox должен фильтровать элементы.

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

Класс контроллера -

public class FinanceActionsController implements Initializable {
    @FXML    
    private ComboBox<BillingPartyOptions> cmbBillingParty;
    @FXML
    private ComboBox<AddressOptions> cmbAddress;
    final ObservableList<BillingPartyOptions> billPartyOptions = FXCollections.observableArrayList();
    final ObservableList<AddressOptions> addressOptions = FXCollections.observableArrayList();
    final Connection con = new DBConnection().getConnection();

  @Override
    public void initialize(URL url, ResourceBundle rb) {
        new ComboBoxAutoComplete<BillingPartyOptions>(cmbBillingParty);
    }

    @FXML
    private void onClickBtnAdd(ActionEvent event) {
        enableOnClickAdd();
        populateCmbBillingParty();
    }

    private void populateCmbBillingParty() {
        try {
            cmbBillingParty.setItems(billPartyOptions);
            cmbAddress.setItems(addressOptions);

            PreparedStatement ps = null;
            ResultSet rs = null;
            ps = con.prepareStatement("SELECT CUSTOMER_ID, CUSTOMER_NAME FROM CUSTOMERS WHERE CUSTOMER_STATUS = 'Y'");
            rs = ps.executeQuery();

            while (rs.next()) {
                billPartyOptions.add(new BillingPartyOptions(rs.getInt("CUSTOMER_ID"), rs.getString("CUSTOMER_NAME")));
            }

            cmbBillingParty.setConverter(new StringConverter<BillingPartyOptions>() {
                @Override
                public String toString(BillingPartyOptions object) {
                    return object.getCustomerName();
                }

                @Override
                public BillingPartyOptions fromString(String string) {
                    return null;
                }
            });

            cmbBillingParty.valueProperty().addListener((obs, oldVal, newVal) -> {
                addressOptions.clear();
                try {
                    int customerID;
                    if (newVal.getCustomerId() == null) {
                        customerID = 0;
                    } else {
                        customerID = newVal.getCustomerId();
                    }
                    PreparedStatement ps1 = con.prepareCall("SELECT 0 AS ADDRESS_ID, CM.ADDRESS, CM.CUSTOMER_ID, CM.STATE_ID FROM CUSTOMERS CM LEFT JOIN ADDRESSES AM ON CM.CUSTOMER_ID = AM.CUSTOMER_ID WHERE CM.CUSTOMER_ID = ? UNION ALL SELECT AM.ADDRESS_ID, AM.ADDRESS, AM.CUSTOMER_ID, AM.STATE_ID FROM ADDRESSES AM INNER JOIN CUSTOMERS CM ON AM.CUSTOMER_ID = CM.CUSTOMER_ID WHERE CM.CUSTOMER_ID = ?");
                    ps1.setInt(1, customerID);
                    ps1.setInt(2, customerID);
                    ResultSet rs1 = ps1.executeQuery();

                    while (rs1.next()) {
                        addressOptions.add(new AddressOptions(rs1.getInt(1), rs1.getString(2), rs1.getInt(3), rs1.getInt(4)));
                    }

                    cmbAddress.setConverter(new StringConverter<AddressOptions>() {
                        @Override
                        public String toString(AddressOptions object) {
                            return object.getAddress();
                        }

                        @Override
                        public AddressOptions fromString(String string) {
                            return null;
                        }
                    });
                } catch (NullPointerException ne) {
                    clearComboBoxes();
                } catch (Exception ex) {
                    clearComboBoxes();
                    System.out.println(ex);
                }
            });

            ps.close();
            rs.close();
            //con.close();
        } catch (Exception e) {
            System.out.println(e.getCause());
        }
    }

Я добавляю объекты класса в список наблюдаемых.

class BillingPartyOptions {

    private Integer customerId;
    private String customerName;

    public BillingPartyOptions(Integer customerId, String customerName) {
        this.customerId = customerId;
        this.customerName = customerName;
    }

    public Integer getCustomerId() {
        return customerId;
    }

    public String getCustomerName() {
        return customerName;
    }
}

class AddressOptions {

    private Integer addressId;
    private String address;
    private Integer customerId;
    private Integer stateId;

    public AddressOptions(Integer addressId, String address, Integer customerId, Integer stateId) {
        this.addressId = addressId;
        this.address = address;
        this.customerId = customerId;
        this.stateId = stateId;
    }

    public Integer getAddressId() {
        return addressId;
    }

    public String getAddress() {
        return address;
    }

    public Integer getStateId() {
        return stateId;
    }

    public Integer getCustomerId() {
        return customerId;
    }
}

Я использую этот класс ниже для фильтра автозаполнения с подсказкой

package controllers;

import java.util.stream.Stream;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Window;

public class ComboBoxAutoComplete<T> {

        private ComboBox<T> cmb;
        String filter = "";
        private ObservableList<T> originalItems;

        public ComboBoxAutoComplete(ComboBox<T> cmb) {
            this.cmb = cmb;
            originalItems = FXCollections.observableArrayList(cmb.getItems());
            cmb.setTooltip(new Tooltip());
            cmb.setOnKeyPressed(this::handleOnKeyPressed);
            cmb.setOnHidden(this::handleOnHiding);
        }

        public void handleOnKeyPressed(KeyEvent e) {
            ObservableList<T> filteredList = FXCollections.observableArrayList();
            KeyCode code = e.getCode();

            if (code.isLetterKey()) {
                filter += e.getText();
            }
            if (code == KeyCode.BACK_SPACE && filter.length() > 0) {
                filter = filter.substring(0, filter.length() - 1);
                cmb.getItems().setAll(originalItems);
            }
            if (code == KeyCode.ESCAPE) {
                filter = "";
            }
            if (filter.length() == 0) {
                filteredList = originalItems;
                cmb.getTooltip().hide();
            } else {
                Stream<T> itens = cmb.getItems().stream();
                String txtUsr = filter.toString().toLowerCase();
                itens.filter(el -> el.toString().toLowerCase().contains(txtUsr)).forEach(filteredList::add);
                cmb.getTooltip().setText(txtUsr);
                Window stage = cmb.getScene().getWindow();
                double posX = stage.getX() + cmb.getBoundsInParent().getMinX();
                double posY = stage.getY() + cmb.getBoundsInParent().getMinY();
                cmb.getTooltip().show(stage, posX, posY);
                cmb.show();
            }
            cmb.getItems().setAll(filteredList);
        }

        public void handleOnHiding(Event e) {
            filter = "";
            cmb.getTooltip().hide();
            T s = cmb.getSelectionModel().getSelectedItem();
            cmb.getItems().setAll(originalItems);
            cmb.getSelectionModel().select(s);
        }

    }

Извините за добавление длинного кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...