问题
I want to create a GridPane (which is nested in a ScrollPane) where I add dynamically cells to the GridPane. Each cell contains a VBox with a BackgroundImage, a few Labels and a Checkbox. The Problem is, that the GridPane can contain several hundreds VBoxes, in my case there are about 300 VBoxes and with this many VBoxes the response time of the Gridpane gets really poor. When I click for instance on a CheckBox it takes a few seconds until the CheckBox is selected/unselected, which makes my program pretty much unusable. Without the BackgroundImage the response time of the GridPane is perfect, so I know that the problem here are the Images
This is my Code to create a VBox:
private VBox createAlbumVBox(Album album) {
VBox container = new VBox();
container.setAlignment(Pos.BOTTOM_LEFT);
CheckBox checkBox = new CheckBox();
Label labelAlbum = new Label(album.getName());
Label labelArtist = new Label(album.getArtistName());
labelAlbum.setStyle("-fx-text-fill: #272727");
labelArtist.setStyle("-fx-text-fill: #272727");
Background background;
if(album.getCover() != null)
{
byte[] coverData = album.getCover();
Image image = new Image(new ByteArrayInputStream(coverData));
BackgroundSize bg = new BackgroundSize(100,100,true,true,true,false);
BackgroundImage backgroundImage = new BackgroundImage(image,BackgroundRepeat.NO_REPEAT,BackgroundRepeat.NO_REPEAT,BackgroundPosition.CENTER,bg);
background = new Background(backgroundImage);
}
else
{
Image image = new Image("/ressources/covers/default-cover.png");
BackgroundSize bg = new BackgroundSize(100,100,true,true,true,false);
BackgroundImage backgroundImage = new BackgroundImage(image,BackgroundRepeat.NO_REPEAT,BackgroundRepeat.NO_REPEAT,BackgroundPosition.CENTER,bg);
background = new Background(backgroundImage);
}
checkBox.setOnMouseClicked(e -> {
if (checkBox.isSelected()) {
album.getTitles().forEach(t -> t.setReadyToSync(true));
} else {
album.getTitles().forEach(t -> t.setReadyToSync(false));
}
});
container.setBackground(background);
HBox hBox = new HBox();
hBox.getChildren().addAll(labelAlbum, labelArtist, checkBox);
hBox.setPrefHeight(30);
hBox.setStyle("-fx-background-color: rgba(255, 255, 255, 0.4)");
container.getChildren().addAll(hBox);
return container;
}
I already tried to use an ImageView instead of a BackgroundImage. Unfortunately the performance with an ImageView is as poor as with a BackgroundImage.
回答1:
This is not really an answer but more a set of suggestions you can try. It's hard to comment on performance issues without a complete mcve, which would allow the issues to be easily reproduced locally in a minimal application.
Some things you could try are:
- Use background loading for your images.
- Cache loaded images in a LRU cache.
- Use a virtualized control, such as a ControlsFX GridView.
See also some of the performance optimization suggestions in a related answer (some of which may not be applicable to your situation):
- What is the best way to display millions of images in Java?
Also, your issue could be in code that you don't show. Your routine is being passed an Album instance which includes album data, including image data in binary form. If you load up your album data and images from a database dynamically, then that process could slow or freeze your application, depending upon how you do it.
来源:https://stackoverflow.com/questions/36318197/javafx-images-in-gridpane-slowing-down-performance-drastically