我在javafx2中制作了一个fxml文件。
我有一个 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 项目中。为此,我在 java Controller 的 Initialize 方法中写道:
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 方面没有足够的经验,并且我不知道我必须如何处理,因为我有一个组合框,其中所有项目的同一单元格中都有成对的图标和文本。
我要向 Peter Duniho 和 PakkuDon 表示衷心的感谢,他们帮助我提高了文本中的英语水平。
最佳答案
使用 Node
几乎总是错误的class 作为 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 ;
}
}
创建 UI 代码 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
的实现的buttonCell
.
这里的要点是,单元格仅为可见单元格创建,因此图像在显示单元格时“按需”加载。使用Image
采用宽度和高度参数的构造函数也减少了内存占用,如 Image
对象可以在加载时调整大小。
最后,请注意,使用该标志在后台加载图像非常重要,这可以保持 UI 的响应能力。如果您快速滚动,您可能会看到一些图像暂时未加载;一旦图像可用,单元格将适本地重新绘制。
关于java - OutOfMemoryError 和 ObservableList 进入 ComboBox 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28132266/