JavaFX 静态 ObservableList 不刷新 ComboBox
JavaFX static ObservableList not refreshing ComboBox
我想做的是有一个 class 来维护国家的静态 ObservableList。我想在 ComboBox 中显示这些国家/地区。我让这部分工作正常。现在,我还想让用户能够将新国家添加到列表中。因此,组合框旁边有一个按钮,它将显示另一个对话框,允许输入另一个国家名称。用户输入国家名称并单击保存后,我希望使用新国家更新单个静态 ObservableList,然后它显示在 ComboBox 中。这部分没有发生。
我将展示哪些有效,哪些无效。
保存对静态列表的引用并进行更新。像这样:
public class CustomerController implements Initializable {
private ObservableList<Country> countryList;
@Override
public void initialize(URL url, ResourceBundle rb) {
countryList = Country.getCountryList();
comboCountry.setItems(countryList);
}
...
// Fired when clicking the "new country" button
@FXML
void handleNewCountry(ActionEvent event) {
Country country = new Country();
country.setCountry("Austria");
countryList.add(country);
}
}
这是我想做的,但它不起作用:
public class CustomerController implements Initializable {
@FXML
private ComboBox<Country> comboCountry;
@Override
public void initialize(URL url, ResourceBundle rb) {
comboCountry.setItems(Country.getCountryList());
}
@FXML
void handleNewCountry(ActionEvent event) {
showScene("Country.fxml", "dialog.newCountry");
}
private void showScene(String sceneResource, String titleResource) {
try {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(sceneResource),
resourceBundle
);
Scene scene = new Scene(loader.load());
getNewStage(resourceBundle.getString(titleResource), scene).showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
private Stage getNewStage(String title, Scene scene) {
Stage stage = new Stage();
stage.setTitle(title);
stage.setResizable(false);
stage.setScene(scene);
stage.initOwner(rootPane.getScene().getWindow());
stage.initModality(Modality.APPLICATION_MODAL);
return stage;
}
}
国家class:
public class Country extends BaseModel {
private int countryID;
private StringProperty country;
private static ObservableList<Country> countryList; // The static observable list
public Country() {
countryList = FXCollections.observableArrayList();
country = new SimpleStringProperty();
}
public int getCountryID() {
return countryID;
}
public void setCountryID(int countryID) {
this.countryID = countryID;
}
public StringProperty countryProperty() {
return this.country;
}
public String getCountry() {
return this.country.get();
}
public void setCountry(String country) {
this.country.set(country);
}
public boolean equals(Country country) {
if (this.getCountry().compareToIgnoreCase(country.getCountry()) != 0) {
return false;
}
return true;
}
public static ObservableList<Country> getCountryList() {
if (countryList.size() < 1) {
updateCountryList();
}
return countryList;
}
public static void updateCountryList() {
countryList.clear();
ArrayList<Country> daoList = CountryDao.listCountries();
for (Country country : daoList) {
countryList.add(country);
}
}
@Override
public String toString() {
return this.getCountry();
}
}
以及输入新国家的对话框:
public class CountryController implements Initializable {
@FXML
private TextField textCountry;
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML
void handleSave(ActionEvent event) {
Country country = new Country();
country.setCountry(textCountry.getText().trim());
CountryDao.insert(country); // Insert the country into the database
Country.updateCountryList(); // Update the static ObservableList
close();
}
@FXML
void handleCancel() {
close();
}
void close() {
final Stage stage = (Stage) textCountry.getScene().getWindow();
stage.close();
}
}
因此,我的理论是 ComboBox 在调用 setItems 时以某种方式创建了 ObservableList 的新实例。不过我真的不确定。一个静态对象应该只有一个实例,因此从任何地方更新它应该更新那个 ComboBox。有人知道这是怎么回事吗?
每次调用 Country
构造函数时,您都会创建一个新的 ObservableList
实例。这样,一个不同于 ComboBox
的列表被修改了。
如果您确实需要在静态字段中保留国家列表(这被认为是不好的做法),您应该确保只创建一个 ObservableList
:
private static final ObservableList<Country> countryList = FXCollections.observableArrayList();
(也从构造函数中删除该字段的赋值。)
我想做的是有一个 class 来维护国家的静态 ObservableList。我想在 ComboBox 中显示这些国家/地区。我让这部分工作正常。现在,我还想让用户能够将新国家添加到列表中。因此,组合框旁边有一个按钮,它将显示另一个对话框,允许输入另一个国家名称。用户输入国家名称并单击保存后,我希望使用新国家更新单个静态 ObservableList,然后它显示在 ComboBox 中。这部分没有发生。
我将展示哪些有效,哪些无效。
保存对静态列表的引用并进行更新。像这样:
public class CustomerController implements Initializable {
private ObservableList<Country> countryList;
@Override
public void initialize(URL url, ResourceBundle rb) {
countryList = Country.getCountryList();
comboCountry.setItems(countryList);
}
...
// Fired when clicking the "new country" button
@FXML
void handleNewCountry(ActionEvent event) {
Country country = new Country();
country.setCountry("Austria");
countryList.add(country);
}
}
这是我想做的,但它不起作用:
public class CustomerController implements Initializable {
@FXML
private ComboBox<Country> comboCountry;
@Override
public void initialize(URL url, ResourceBundle rb) {
comboCountry.setItems(Country.getCountryList());
}
@FXML
void handleNewCountry(ActionEvent event) {
showScene("Country.fxml", "dialog.newCountry");
}
private void showScene(String sceneResource, String titleResource) {
try {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(sceneResource),
resourceBundle
);
Scene scene = new Scene(loader.load());
getNewStage(resourceBundle.getString(titleResource), scene).showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
private Stage getNewStage(String title, Scene scene) {
Stage stage = new Stage();
stage.setTitle(title);
stage.setResizable(false);
stage.setScene(scene);
stage.initOwner(rootPane.getScene().getWindow());
stage.initModality(Modality.APPLICATION_MODAL);
return stage;
}
}
国家class:
public class Country extends BaseModel {
private int countryID;
private StringProperty country;
private static ObservableList<Country> countryList; // The static observable list
public Country() {
countryList = FXCollections.observableArrayList();
country = new SimpleStringProperty();
}
public int getCountryID() {
return countryID;
}
public void setCountryID(int countryID) {
this.countryID = countryID;
}
public StringProperty countryProperty() {
return this.country;
}
public String getCountry() {
return this.country.get();
}
public void setCountry(String country) {
this.country.set(country);
}
public boolean equals(Country country) {
if (this.getCountry().compareToIgnoreCase(country.getCountry()) != 0) {
return false;
}
return true;
}
public static ObservableList<Country> getCountryList() {
if (countryList.size() < 1) {
updateCountryList();
}
return countryList;
}
public static void updateCountryList() {
countryList.clear();
ArrayList<Country> daoList = CountryDao.listCountries();
for (Country country : daoList) {
countryList.add(country);
}
}
@Override
public String toString() {
return this.getCountry();
}
}
以及输入新国家的对话框:
public class CountryController implements Initializable {
@FXML
private TextField textCountry;
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML
void handleSave(ActionEvent event) {
Country country = new Country();
country.setCountry(textCountry.getText().trim());
CountryDao.insert(country); // Insert the country into the database
Country.updateCountryList(); // Update the static ObservableList
close();
}
@FXML
void handleCancel() {
close();
}
void close() {
final Stage stage = (Stage) textCountry.getScene().getWindow();
stage.close();
}
}
因此,我的理论是 ComboBox 在调用 setItems 时以某种方式创建了 ObservableList 的新实例。不过我真的不确定。一个静态对象应该只有一个实例,因此从任何地方更新它应该更新那个 ComboBox。有人知道这是怎么回事吗?
每次调用 Country
构造函数时,您都会创建一个新的 ObservableList
实例。这样,一个不同于 ComboBox
的列表被修改了。
如果您确实需要在静态字段中保留国家列表(这被认为是不好的做法),您应该确保只创建一个 ObservableList
:
private static final ObservableList<Country> countryList = FXCollections.observableArrayList();
(也从构造函数中删除该字段的赋值。)