JavaFX ListView无法渲染足够的单元格来填充其视口

时间:2016-07-24 17:42:13

标签: java listview javafx javafx-8

我有这个音乐播放应用程序,可以在网格中显示艺术家和专辑。我使用ListView和自定义ListCells创建了这个网格。但是,ListView在初始化时似乎不会渲染超过2个单元格,即使它的高度足以渲染3行或4行,具体取决于屏幕的大小。但是,当前两个单元格中的一个悬停时,ListView会渲染剩余的单元格。请查看下面的链接,了解实际问题。

demo of the issue

我已经检查了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);
    }
}

自定义ListCell:

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;
    }
}

1 个答案:

答案 0 :(得分:0)

我整理了一个测试,并使用一个静态图像为艺术家体验了这个问题。如果我用一个简单的矩形替换了ListCell中的行构建它可以正常工作,那么瓶颈似乎是构建你的HBox / VBox单元。

在grid.setItems之后将调用移动到setCellFactory似乎解决了它。

grid.setItems(rows);
grid.setCellFactory(x -> new ArtistListCell<>());

我会说这样做是为了调用另一个布局传递,而另一种方式是没有正确计算所需的所有信息?

如果花费时间,您可能会使用正确的图像加载获得不同的结果。如果是这样,如果您还在使用它,可能会使用占位符图像?