JavaFX не может выбрать ComboBox с настраиваемым классом - PullRequest
0 голосов
/ 25 мая 2020

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

//I chose to use Customer instead of String so I can have duplicates and save the right one later
@FXML private ComboBox<Customer> selectionBox;

public void initialize() {
    // Adding all customers here, simplified example:
    int id = 1;
    String name = "Grace";
    Customer customer = new Customer(id, name);
    selectionBox.getItems().add(customer);
}

Это упрощение моего класса Customer:

public class Customer {
    private int id;
    private int name;

    public Customer(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString() {
        // This is here to show the name in the ComboBox instead of 'Customer.java@37hf'
        return name;
    }
}

И мой класс заказа:

public class Order {
    private int id;
    private Customer customer;    

    public Order(int id, Customer customer) {
        this.id = id;
        this.customer = customer
    }

    public void saveSql(Customer newCustomer) {
        this.customer = newCustomer;
        // Sql code here
    }
}

Всякий раз, когда я хочу обновить заказ с новым клиентом и сделать
order.saveSql(selectionBox.getSelectionModel().getSelectedItem())
, он выдает эту ошибку:
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class java.lang.String cannot be cast to class my.package.Customer
Это говорит о том, что selectionBox.getSelectionModel().getSelectedItem() является String, в то время как eclipse говорит, что это «Клиент», и он должен быть клиентом, поскольку я инициализировал ComboBox, используя ComboBox<Customer>

Что я могу с этим поделать?
Спасибо за помощь!

1 Ответ

1 голос
/ 26 мая 2020

Вы получаете ошибку String, потому что то, что вы пишете, когда a ComboBox доступно для редактирования, это TextField, которое возвращает String. Когда вы снимаете фокус с этого поля (например, нажимаете Alt + Tab, щелкаете по другому полю и т. Д. c.) Или нажимаете «Enter», система пытается добавить этот String в список ComboBox, но поскольку указанный ComboBox относится к типу Customer, он не может.

Чтобы справиться с этим, вам нужно использовать StringConverter. См. this о том, как этого добиться.

EDIT :

Попробовав, я нашел this . Мне удалось адаптировать его к вашему случаю.

package sample;

public class Customer {
    private int id;
    private String name;

    public Customer(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters & Setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // You don't need to override the toString() method for this
}

CustomerConverter - это нестандартный Converter класс.

package sample;

import javafx.util.StringConverter;

public class CustomerConverter extends StringConverter<Customer> {

    private int customerId;

    // Method to convert a Customer-Object to a String
    @Override
    public String toString(Customer customer)
    {
        return customer == null? null : customer.getName();
    }

    // Method to convert a String to a Customer-Object
    @Override
    public Customer fromString(String string) {

        Customer customer = null;

        if (string == null) {
            return customer;
        }

        customer = new Customer(customerId, string);

        return customer;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

}

Controller класс из FXML.

package sample;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

public class Controller implements Initializable {

    @FXML
    ComboBox<Customer> selectionBox;

    private ArrayList<Customer> customerList = new ArrayList<Customer>();

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

        selectionBox.getItems().addAll(addItemsToComboBox());
        selectionBox.setConverter(new CustomerConverter());

        // This will add the New Customer object from the ComboBox's TextField to the list of Customers
        // on pressing ENTER
        selectionBox.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.ENTER) {

                // To create a new ID, get the total number of items in the ArrayList of Customer objects
                // and add 1.

                // You can also call your Order method here or read the ArrayList and get the Customer from there.
                addCustomer(new Customer(customerList.size() + 1, selectionBox.getEditor().getText()));
            }
        });

        // By default, when the ComboBox TextField is un-focused, the system will try to add it to the list
        // You can tell by the 'System.out.print's in the two methods below this one, but by doing things this
        // way, it will not be able to because your ComboBox is populated by the ArrayList.
        // If you still want to add Customer Objects when it's un-focused, uncomment this part.
        /*selectionBox.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observableValue, Boolean outOfFocus, Boolean onFocus) {

                if (outOfFocus) {

                    // You can also call your Order method here or read the ArrayList and get the Customer from there.
                    addCustomer(new Customer(customerList.size() + 1, selectionBox.getEditor().getText()));
                }
            }
        });*/

        // Handles the selected Customer item from the ComboBox.
        selectionBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Customer>() {
            public void changed(ObservableValue<? extends Customer> ov,
                                final Customer oldvalue, final Customer newvalue) {

                // This IF check exists, because the first time you select an item,
                // there will be no old item that has been previously selected.
                // If this check is removed, you'll get a NullPointerException when trying to get values from
                // 'oldvalue' Object.
                if (oldvalue != null){
                    System.out.println("Customer changed from: " + oldvalue.getName()
                            + " with ID: " +oldvalue.getId() + " to: "
                            + newvalue.getName() + " with ID: " + newvalue.getId());
                }
                else {
                    System.out.println("New customer has been selected who's name is: "
                            + newvalue.getName() + " with ID: " + newvalue.getId());
                }
            }
        });

        // Handles the selected Customer item index from the ComboBox.
        selectionBox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>()
        {
            public void changed(ObservableValue<? extends Number> ov,
                                final Number oldvalue, final Number newvalue) {

                System.out.println("Old ComboBox Index: " + oldvalue + " changed to: " + newvalue);
            }
        });


    }

    // Adds a new Customer Object to the list.
    // Clears the ComboBox and re-populates it.
    public void addCustomer(Customer customer) {

        customerList.add(customer);

        selectionBox.getItems().clear();
        selectionBox.getItems().addAll(customerList);

    }

    // Adds the initial Customer Objects for testing purposes.
    public ArrayList<Customer> addItemsToComboBox(){

        customerList = new ArrayList<Customer>();

        customerList.add(new Customer(1,"John"));
        customerList.add(new Customer(2,"Mark"));
        customerList.add(new Customer(3,"Roger"));
        customerList.add(new Customer(4,"David"));
        customerList.add(new Customer(5,"Rick"));

        return customerList;
    }

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