JavaFX 无法使用自定义选择 ComboBox class
JavaFX can't get selection of ComboBox with custom class
我想给我的订单一个新客户,所以我创建了一个组合框,其中包含我可以选择的所有客户:
//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);
}
这是我的客户的简化 class:
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;
}
}
还有我的订单class:
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()
是一个字符串,而 eclipse 说它是一个 'Customer' 并且它应该是一个客户,因为我使用 ComboBox<Customer>
初始化了 ComboBox
我该怎么办?
感谢您的帮助!
您收到 String
错误,因为当 ComboBox
可编辑时,您正在写入的内容是 TextField
,而 returns a String
。当您从该字段 "un-focus"(例如按 Alt+Tab,单击另一个字段等)或按 "Enter" 时,系统会尝试将 String
添加到 ComboBox
列表,但由于所述 ComboBox
是 Customer
类型,所以它不能。
要管理它,您需要使用 StringConverter
。请参阅 了解如何实现。
编辑:
折腾了一下,找到了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
class.
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
class 的 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;
}
}
我想给我的订单一个新客户,所以我创建了一个组合框,其中包含我可以选择的所有客户:
//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);
}
这是我的客户的简化 class:
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;
}
}
还有我的订单class:
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()
是一个字符串,而 eclipse 说它是一个 'Customer' 并且它应该是一个客户,因为我使用 ComboBox<Customer>
我该怎么办?
感谢您的帮助!
您收到 String
错误,因为当 ComboBox
可编辑时,您正在写入的内容是 TextField
,而 returns a String
。当您从该字段 "un-focus"(例如按 Alt+Tab,单击另一个字段等)或按 "Enter" 时,系统会尝试将 String
添加到 ComboBox
列表,但由于所述 ComboBox
是 Customer
类型,所以它不能。
要管理它,您需要使用 StringConverter
。请参阅
编辑:
折腾了一下,找到了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
class.
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
class 的 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;
}
}