【发布时间】:2016-11-28 00:54:34
【问题描述】:
我有这个音乐播放应用程序,它以网格形式显示艺术家和专辑。我使用 ListView 和自定义 ListCells 创建了这个网格。但是,ListView 在初始化时似乎不会渲染超过 2 个单元格,即使它的高度足够大,可以根据屏幕大小渲染 3 或 4 行。但是,当前 2 个单元格中的一个悬停在上面时,ListView 会渲染剩余的单元格。请查看下面的链接以了解实际问题。
我检查了 ListView 的高度,它确实在扩展以填充其父级,所以我相信 ListView 决定哪些单元格需要呈现的方式有些奇怪。我希望找到一种方法来强制 ListView 呈现正确数量的单元格,如果这是根本问题,或者如果我的代码中有错误,那么对此也有一些了解会很棒。我已经在下面发布了我的控制器和我的自定义 ListCell 的代码。
初始化 ListView 的控制器:
public class ArtistsController implements Initializable {
@FXML
private ListView<ArrayList<Artist>> grid;
@Override
public void initialize(URL location, ResourceBundle resources) {
List<Artist> artists = Library.getArtists();
Collections.sort(artists);
grid.setCellFactory(x -> new ArtistListCell<>());
ObservableList<ArrayList<Artist>> rows = FXCollections.observableArrayList();
ArrayList<Artist> row = new ArrayList<>();
int col;
for (int i = 0; i < artists.size(); i++) {
col = i % 5;
if (col == 0) {
row = new ArrayList<>();
rows.add(row);
}
row.add(artists.get(i));
}
grid.setItems(rows);
}
}
自定义列表单元:
public class ArtistListCell<T extends ArrayList<Artist>> extends ListCell<T> {
private T item;
public ArtistListCell() {
this.getStyleClass().setAll("artist-list-cell");
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else if (!item.equals(this.item)) {
this.item = item;
HBox row = new HBox();
item.forEach(artist -> {
VBox cell = createCell(artist);
row.getChildren().add(cell);
});
setGraphic(row);
}
}
private VBox createCell(Artist artist) {
VBox cell = new VBox();
Label title = new Label(artist.getTitle());
ImageView image = new ImageView(artist.getArtistImage());
image.imageProperty().bind(artist.artistImageProperty());
VBox imageBox = new VBox();
title.setTextOverrun(OverrunStyle.CLIP);
title.setWrapText(true);
title.setPadding(new Insets(10, 0, 10, 0));
title.setAlignment(Pos.TOP_LEFT);
title.setPrefHeight(66);
title.prefWidthProperty().bind(this.widthProperty().subtract(102).divide(5));
image.fitWidthProperty().bind(this.widthProperty().subtract(102).divide(5));
image.fitHeightProperty().bind(this.widthProperty().subtract(102).divide(5));
image.setPreserveRatio(true);
image.setSmooth(true);
imageBox.prefWidthProperty().bind(this.widthProperty().subtract(102).divide(5));
imageBox.prefHeightProperty().bind(this.widthProperty().subtract(102).divide(5));
imageBox.setAlignment(Pos.CENTER);
imageBox.getChildren().add(image);
cell.getChildren().addAll(imageBox, title);
cell.setPadding(new Insets(10, 10, 0, 10));
cell.getStyleClass().add("artist-cell");
cell.setAlignment(Pos.CENTER);
cell.setOnMouseClicked(event -> {
// do something
});
cell.setOnDragDetected(event -> {
// do something
});
return cell;
}
}
【问题讨论】:
-
图片有多大,如何加载?
-
它们是 300x300 像素的 .jpg,每个大约 20KB。它们的加载方式如下: Image image = new Image("file path goes here");
-
可能是加载图像的问题。尝试确保在显示场景之前加载图像,例如通过将它们存储在地图中并将它们放入
createCell并检查这是否会改变行为。 (我猜您现在正在使用图像构造函数在createCell中创建图像。)此外,如果createCell方法不是很大,您能否将其添加(或允许重现问题的简化版本)到问题? -
好的,createCell 方法的大部分内容我都填写了。此外,图像不会在 createCell 中加载。它们在应用程序启动时加载,然后由 artist.getArtistImage() 检索。
标签: java listview javafx javafx-8