OutOfMemoryError и проблемы с ObservableList в ComboBox
Я делаю fxml файл в javafx2.
У меня есть объекты List of Person. Название этого списка Entries
, У меня есть ObservableList, myObservableList
, Внутри этого я хочу поставить этикетки. Каждый ярлык должен содержать пару изображений человека и текст его имени. Я пишу этот код:
for (int i=0; i<numberOfEntries; i++){
currentEntry = Entries.get(i);
name=currentEntry.getName();
image1 = new Image("file:"+currentEntry.getIcon());
imageView1= new ImageView();
imageView1.setFitHeight(50);
imageView1.setFitWidth(70);
imageView1.setImage(image1);
label = new Label(name, imageView1);
label.setFont(new Font("serif", 32));
myObservableList.add(label);
}
Это работает нормально, но после нескольких вставок изображений JVM выдает мне следующее сообщение об ошибке:
Caused by: java.lang.OutOfMemoryError: Java heap space.
Эта ошибка происходит из строки кода image1 = new Image("file:"+currentEntry.getIcon());
Наконец, я хочу поместить все элементы myObservableList в элементы ComboBox. По этой причине в методе Initialize Java-контроллера я пишу:
myComboBox.setItems(myObservableList);
ListCell<Label> buttonCell = new ListCell<Label>() {
@Override protected void updateItem(Label item, boolean isEmpty) {
super.updateItem(item, isEmpty);
setText(item==null ? "" : item.getText());
}
};
myComboBox.setButtonCell(buttonCell);
Я уверен, что у меня недостаточно опыта в javafx, и я не знаю, как мне поступить, потому что у меня есть комбинированный список с парами значков и текста в одной ячейке для всех элементов.
Я хочу поблагодарить Питера Дунихо и ПаккуДона за помощь в улучшении английского языка в моем тексте.
1 ответ
Почти всегда ошибка использовать Node
класс в качестве типа данных для ComboBox
(или для любого другого контроля). Вы должны использовать класс, который представляет только данные, и зарегистрировать фабрику ячеек, чтобы настроить способ отображения данных.
В вашем случае, если вы включите изображение в данные, вы, скорее всего, столкнетесь с проблемами памяти. Каждое изображение, вероятно, будет представлено в памяти несколькими мегабайтами. Таким образом, ваш класс данных должен содержать имя изображения, а затем вы можете использовать ячейку в поле со списком для создания изображения.
Вот пример кода, чтобы дать вам идею:
Класс данных (Person.java):
public class Person {
private final String name ;
private final String imageFileName ;
public Person(String name, String imageFileName) {
this.name = name ;
this.imageFileName = imageFileName ;
}
public String getName() {
return name ;
}
public String getImageFileName() {
return imageFileName ;
}
}
Код пользовательского интерфейса для создания ComboBox
из List<Person>
:
List<Person> entries = ... ; // populated from DB
ComboBox<Person> comboBox = new ComboBox<>();
comboBox.getItems().addAll(entries);
comboBox.setCellFactory(new Callback<ListView<Person>, ListCell<Person>>() {
@Override
public ListCell<Person> call(ListView<Person> listCell) {
return new ListCell<Person>() {
private final ImageView = new ImageView();
@Override
public void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
File imageFile = new File(person.getImageFileName());
String imageUrl = imageFile.toURI().toURL().toExternalForm();
Image image = new Image(imageUrl, 70, 50,
// preserve ratio
true,
// smooth resizing
true,
// load in background
true);
imageView.setImage(image);
setText(person.getName());
setGraphic(imageView);
}
}
};
}
});
Вы можете использовать то же самое ListCell
реализация для ComboBox
"s buttonCell
,
Дело в том, что ячейки создаются только для видимых ячеек, поэтому изображения загружаются "по требованию" при отображении ячеек. С использованием Image
Конструктор, который принимает параметры ширины и высоты, также уменьшает объем памяти, так как Image
объект может изменить размер при загрузке.
Наконец, обратите внимание, что важно использовать флаг для загрузки изображений в фоновом режиме, что поддерживает адаптивный интерфейс. Если вы прокрутите быстро, вы, вероятно, увидите, что некоторые изображения не загружаются в течение короткого времени; клетки будут перекрашиваться соответствующим образом, как только изображение станет доступным.