带有 cellfactory 的 javafx ComboBox 不显示所选项目
javafx ComboBox with cellfactory does not display selected item
我有一个小型概念验证应用程序,其中包含 6 Labels
、一个 ComboBox
和一个 Button
,全部使用 SceneBuilder 创建。
通过单击 Button
,该应用会 Json api 调用 return 国家列表及其相关详细信息(apla2code、apla3code、名称等).我创建了一个包含 3 个 String
元素的 CountryDetails
对象。我用它来 return 一个 CountryDetails
的数组,然后我将它加载到一个 ObserbavleList
的数组中。然后,我将其应用于 ComboBox
,每次在 ComboBox
中选择一个项目时,我将 CountryDetails
元素加载到 3 个标签中。所有这一切都很好(尽管可能有更好的方法)。
我遇到的问题是 ComboBox
没有显示所选项目,我不知道如何更正此问题。下图显示了问题所在。
调用api的代码如下:
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetCountries {
public CountryDetails[] getDetails() {
String inputLine = "";
StringBuilder jsonString = new StringBuilder();
HttpURLConnection urlConnection;
try {
URL urlObject = new URL("https://restcountries.eu/rest/v2/all");
urlConnection = (HttpURLConnection) urlObject.openConnection();
urlConnection.setRequestMethod("GET");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
while ((inputLine = bufferedReader.readLine()) != null) {
jsonString.append(inputLine);
}
urlConnection.getInputStream().close();
} catch(IOException ioe) {
System.out.println(ioe.getMessage());
}
Countries[] countries = new Gson().fromJson(jsonString.toString(), Countries[].class);
CountryDetails[] countryDetails = new CountryDetails[countries.length];
for(int i = 0; i < countries.length; i++){
countryDetails[i] = new CountryDetails(
countries[i].getAlpha2Code(),
countries[i].getAlpha3Code(),
countries[i].getName()
);
}
return countryDetails;
}
}
CountryDetails
对象的代码如下:
public class CountryDetails {
private String alpha2Code;
private String alpha3Code;
private String name;
public CountryDetails(String strAlpha2Code, String strAlpha3Code, String strName) {
this.alpha2Code = strAlpha2Code;
this.alpha3Code = strAlpha3Code;
this.name = strName;
}
public String getAlpha2Code() { return alpha2Code; }
public void setAlpha2Code(String alpha2Code) { this.alpha2Code = alpha2Code; }
public String getAlpha3Code() { return alpha3Code; }
public void setAlpha3Code(String alpha3Code) { this.alpha3Code = alpha3Code; }
public String getName() { return name; }
public void setName(String name) {this.name = name; }
}
加载ObservableList
的代码如下:
GetCountries countries = new GetCountries();
CountryDetails[] countryDetails = countries.getDetails();
for (CountryDetails countryDetail : countryDetails) {
countriesObservableList.add(new CountryDetails(
countryDetail.getAlpha2Code(),
countryDetail.getAlpha3Code(),
countryDetail.getName())
);
}
加载ComboBox
并显示Labels
中元素的代码如下:
cbCountryList.setCellFactory(new Callback<ListView<CountryDetails>, ListCell<CountryDetails>>() {
@Override public ListCell<CountryDetails> call(ListView<CountryDetails> p) {
return new ListCell<CountryDetails>() {
@Override
protected void updateItem(CountryDetails item, boolean empty) {
super.updateItem(item, empty);
if (empty || (item == null) || (item.getName() == null)) {
setText(null);
} else {
setText(item.getName());
}
}
};
}
});
public void comboAction(ActionEvent event) {
lblAlpha2Code.setText(cbCountryList.getValue().getAlpha2Code());
lblAlpha3Code.setText(cbCountryList.getValue().getAlpha3Code());
lblCountryName.setText(cbCountryList.getValue().getName());
}
下面是应用程序的图像:
The problem I am having is that the ComboBox is not displaying the selected item and I cannot figure out how to correct this.
您需要为您的cbCountryList
设置一个StringConverter。
cbCountryList.setConverter(new StringConverter<CountryDetails>() {
@Override
public String toString(CountryDetails object) {
return object.getName();
}
@Override
public CountryDetails fromString(String string) {
return null;
}
});
The All of this works fine (although there is probably a much better way of doing this).
您可以考虑更新以下内容,
- HTTP 请求和加载项的异步调用
- 您可以在每次触发按钮时调用时缓存您的
fetched-country
列表。您可以为 GetCountries
. 创建一个 Singleton 对象
已修改 GetCountries
class,
它缓存国家列表并将缓存的数据用于多个请求,
public static class GetCountries {
private static final String API_URL = "https://restcountries.eu/rest/v2/all";
private static CountryDetails[] countryDetails;
public static CountryDetails[] getDetails() {
//uses cached countryDetails once it gets loaded
if (countryDetails != null) {
return countryDetails;
}
StringBuilder jsonString = new StringBuilder();
HttpURLConnection urlConnection;
try {
URL urlObject = new URL(API_URL);
urlConnection = (HttpURLConnection) urlObject.openConnection();
urlConnection.setRequestMethod(HttpMethod.GET.name());
String inputLine = "";
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
while ((inputLine = bufferedReader.readLine()) != null) {
jsonString.append(inputLine);
}
urlConnection.getInputStream().close();
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
Countries[] countries = new Gson().fromJson(jsonString.toString(), Countries[].class);
countryDetails = new CountryDetails[countries.length];
for (int i = 0; i < countries.length; i++) {
countryDetails[i] = new CountryDetails(
countries[i].getAlpha2Code(),
countries[i].getAlpha3Code(),
countries[i].getName()
);
}
return countryDetails;
}
}
使用 Task 异步获取您的国家/地区,
Task<CountryDetails[]> fetchCountryTask = new Task<CountryDetails[]>() {
@Override
protected CountryDetails[] call() throws Exception {
return GetCountries.getDetails();
}
};
fetchButton.setOnAction(event -> new Thread(fetchCountryTask).start());
fetchCountryTask.setOnRunning(event -> cbCountryList.setDisable(true));
fetchCountryTask.setOnSucceeded(e -> {
cbCountryList.getItems().addAll(fetchCountryTask.getValue());
cbCountryList.setDisable(false);
});
我有一个小型概念验证应用程序,其中包含 6 Labels
、一个 ComboBox
和一个 Button
,全部使用 SceneBuilder 创建。
通过单击 Button
,该应用会 Json api 调用 return 国家列表及其相关详细信息(apla2code、apla3code、名称等).我创建了一个包含 3 个 String
元素的 CountryDetails
对象。我用它来 return 一个 CountryDetails
的数组,然后我将它加载到一个 ObserbavleList
的数组中。然后,我将其应用于 ComboBox
,每次在 ComboBox
中选择一个项目时,我将 CountryDetails
元素加载到 3 个标签中。所有这一切都很好(尽管可能有更好的方法)。
我遇到的问题是 ComboBox
没有显示所选项目,我不知道如何更正此问题。下图显示了问题所在。
调用api的代码如下:
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetCountries {
public CountryDetails[] getDetails() {
String inputLine = "";
StringBuilder jsonString = new StringBuilder();
HttpURLConnection urlConnection;
try {
URL urlObject = new URL("https://restcountries.eu/rest/v2/all");
urlConnection = (HttpURLConnection) urlObject.openConnection();
urlConnection.setRequestMethod("GET");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
while ((inputLine = bufferedReader.readLine()) != null) {
jsonString.append(inputLine);
}
urlConnection.getInputStream().close();
} catch(IOException ioe) {
System.out.println(ioe.getMessage());
}
Countries[] countries = new Gson().fromJson(jsonString.toString(), Countries[].class);
CountryDetails[] countryDetails = new CountryDetails[countries.length];
for(int i = 0; i < countries.length; i++){
countryDetails[i] = new CountryDetails(
countries[i].getAlpha2Code(),
countries[i].getAlpha3Code(),
countries[i].getName()
);
}
return countryDetails;
}
}
CountryDetails
对象的代码如下:
public class CountryDetails {
private String alpha2Code;
private String alpha3Code;
private String name;
public CountryDetails(String strAlpha2Code, String strAlpha3Code, String strName) {
this.alpha2Code = strAlpha2Code;
this.alpha3Code = strAlpha3Code;
this.name = strName;
}
public String getAlpha2Code() { return alpha2Code; }
public void setAlpha2Code(String alpha2Code) { this.alpha2Code = alpha2Code; }
public String getAlpha3Code() { return alpha3Code; }
public void setAlpha3Code(String alpha3Code) { this.alpha3Code = alpha3Code; }
public String getName() { return name; }
public void setName(String name) {this.name = name; }
}
加载ObservableList
的代码如下:
GetCountries countries = new GetCountries();
CountryDetails[] countryDetails = countries.getDetails();
for (CountryDetails countryDetail : countryDetails) {
countriesObservableList.add(new CountryDetails(
countryDetail.getAlpha2Code(),
countryDetail.getAlpha3Code(),
countryDetail.getName())
);
}
加载ComboBox
并显示Labels
中元素的代码如下:
cbCountryList.setCellFactory(new Callback<ListView<CountryDetails>, ListCell<CountryDetails>>() {
@Override public ListCell<CountryDetails> call(ListView<CountryDetails> p) {
return new ListCell<CountryDetails>() {
@Override
protected void updateItem(CountryDetails item, boolean empty) {
super.updateItem(item, empty);
if (empty || (item == null) || (item.getName() == null)) {
setText(null);
} else {
setText(item.getName());
}
}
};
}
});
public void comboAction(ActionEvent event) {
lblAlpha2Code.setText(cbCountryList.getValue().getAlpha2Code());
lblAlpha3Code.setText(cbCountryList.getValue().getAlpha3Code());
lblCountryName.setText(cbCountryList.getValue().getName());
}
下面是应用程序的图像:
The problem I am having is that the ComboBox is not displaying the selected item and I cannot figure out how to correct this.
您需要为您的cbCountryList
设置一个StringConverter。
cbCountryList.setConverter(new StringConverter<CountryDetails>() {
@Override
public String toString(CountryDetails object) {
return object.getName();
}
@Override
public CountryDetails fromString(String string) {
return null;
}
});
The All of this works fine (although there is probably a much better way of doing this).
您可以考虑更新以下内容,
- HTTP 请求和加载项的异步调用
- 您可以在每次触发按钮时调用时缓存您的
fetched-country
列表。您可以为GetCountries
. 创建一个 Singleton 对象
已修改 GetCountries
class,
它缓存国家列表并将缓存的数据用于多个请求,
public static class GetCountries {
private static final String API_URL = "https://restcountries.eu/rest/v2/all";
private static CountryDetails[] countryDetails;
public static CountryDetails[] getDetails() {
//uses cached countryDetails once it gets loaded
if (countryDetails != null) {
return countryDetails;
}
StringBuilder jsonString = new StringBuilder();
HttpURLConnection urlConnection;
try {
URL urlObject = new URL(API_URL);
urlConnection = (HttpURLConnection) urlObject.openConnection();
urlConnection.setRequestMethod(HttpMethod.GET.name());
String inputLine = "";
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
while ((inputLine = bufferedReader.readLine()) != null) {
jsonString.append(inputLine);
}
urlConnection.getInputStream().close();
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
Countries[] countries = new Gson().fromJson(jsonString.toString(), Countries[].class);
countryDetails = new CountryDetails[countries.length];
for (int i = 0; i < countries.length; i++) {
countryDetails[i] = new CountryDetails(
countries[i].getAlpha2Code(),
countries[i].getAlpha3Code(),
countries[i].getName()
);
}
return countryDetails;
}
}
使用 Task 异步获取您的国家/地区,
Task<CountryDetails[]> fetchCountryTask = new Task<CountryDetails[]>() {
@Override
protected CountryDetails[] call() throws Exception {
return GetCountries.getDetails();
}
};
fetchButton.setOnAction(event -> new Thread(fetchCountryTask).start());
fetchCountryTask.setOnRunning(event -> cbCountryList.setDisable(true));
fetchCountryTask.setOnSucceeded(e -> {
cbCountryList.getItems().addAll(fetchCountryTask.getValue());
cbCountryList.setDisable(false);
});