Lorsqu'une instance de ʻImage` est créée normalement, l'image est chargée de manière synchrone (aucun traitement n'est renvoyé tant que le chargement n'est pas terminé).
Si l'image est petite, il n'y a pas de problème particulier, mais si une grande image est affichée, le traitement est interrompu pendant un certain temps, ce qui peut nuire à l'opérabilité.
ʻPour charger une image dans l'instance Image en arrière-plan, spécifiez truepour l'argument du constructeurbackgroundLoading.  Il existe deux constructeurs qui peuvent spécifier backgroundLoading`.
Si vous créez une instance avec true pour backgroundLoading, l'image sera chargée de manière asynchrone.
Cela permet au processus de se poursuivre sans s'arrêter.
Si vous placez simplement la charge en arrière-plan, l'image ne sera pas affichée tant que le chargement n'est pas terminé.
Si la taille est grande et que le chargement prend beaucoup de temps, le fait qu'aucune image ne s'affiche peut être gênant pour l'utilisateur. Par conséquent, il peut être bon d'afficher la progression de la charge avec une barre de progression ou autre.
La classe ʻImage` peut connaître la progression du chargement progress Offrir des propriétés. Si vous l'utilisez, vous pouvez afficher la progression du chargement assez facilement.

main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<BorderPane style="-fx-padding: 10px;" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.javafx.MainController">
   <center>
      <VBox alignment="CENTER" minHeight="0.0" minWidth="0.0" BorderPane.alignment="CENTER">
         <children>
            <ProgressBar fx:id="progressBar" maxWidth="1.7976931348623157E308" progress="0.0" />
            <ImageView fx:id="imageView" fitHeight="200.0" fitWidth="300.0" pickOnBounds="true" preserveRatio="true" />
         </children>
      </VBox>
   </center>
</BorderPane>
MainController.java
package sample.javafx;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ProgressBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ResourceBundle;
public class MainController implements Initializable {
    @FXML
    private ProgressBar progressBar;
    @FXML
    private ImageView imageView;
    public void initStage(Stage stage) {
        stage.setWidth(500);
        stage.setHeight(400);
    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        progressBar.managedProperty().bind(progressBar.visibleProperty());
        progressBar.visibleProperty().bind(progressBar.progressProperty().lessThan(1));
        
        imageView.managedProperty().bind(imageView.visibleProperty());
        imageView.visibleProperty().bind(progressBar.progressProperty().isEqualTo(1));
        
        Image image = new Image(Paths.get("./image/shirakawago.jpg ").toUri().toString(), true);
        progressBar.progressProperty().bind(image.progressProperty());
        imageView.setImage(image);
    }
}

C'est un peu rapide et déroutant, mais la barre de progression s'affiche pendant le chargement de l'image et l'image s'affiche lorsque le chargement est terminé.

ProgressBar à côté de ʻImageView` pour l'affichage de l'imageMainController.java
        progressBar.managedProperty().bind(progressBar.visibleProperty());
        progressBar.visibleProperty().bind(progressBar.progressProperty().lessThan(1));
        
        imageView.managedProperty().bind(imageView.visibleProperty());
        imageView.visibleProperty().bind(progressBar.progressProperty().isEqualTo(1));
visible pour afficher uniquement la barre de progression pendant le chargement et uniquement l'image lorsque le chargement est terminé.visible est obtenu en se liant à la valeur de la propriété progress de la barre de progression.MainController.java
        Image image = new Image(Paths.get("./image/shirakawago.jpg ").toUri().toString(), true);
        progressBar.progressProperty().bind(image.progressProperty());
--Spécifiez true pour backgroundLoading dans l'argument du constructeur lors de la génération de ʻImage`
progress de ʻImage à la propriété progress` de la barre de progressionLe chargement en arrière-plan peut être utilisé non seulement en chargeant l'image actuellement affichée, mais aussi en préchargeant l'image à afficher ensuite.
Dans ce cas, seule l'instance ʻImage est générée en arrière-plan, et lors du changement d'image, l'instance ʻImage est remplacée par ʻensembleImage () ʻof ʻImageView`.
image
@FXML
private ImageView imageView;
private Image nextImage;
public void initialize(URL location, ResourceBundle resources) {
    //Chargez l'image suivante en arrière-plan
    nextImage = new Image("next-image.jpg ", true);
    Image initialImage = new Image("initial-image.jpg ", true);
    imageView.setImage(initialImage);
}
@FXML
public void nextPage() {
    //Définir la prochaine image chargée
    imageView.setImage(nextImage);
}
Même les images lourdes peuvent être affichées rapidement en les chargeant à l'avance, ce qui peut conduire à une amélioration de l'opérabilité.
Il est à noter que le préchargement peut améliorer la vitesse d'affichage, mais au prix d'une consommation de mémoire accrue.
En particulier, il est à noter qu'il existe une grande différence entre la taille de l'image sur le disque et la taille lorsqu'elle est chargée en mémoire. Sur le disque, par exemple, une image JPEG a une taille considérablement compressée, alors qu'elle est décompressée lorsqu'elle est chargée en mémoire avec ʻImage`.
Je vais étudier à quel point c'est différent.

Voici la taille sur le disque, environ 6,5 Mo.
Chargez cette image avec ʻImage, puis effectuez un vidage de tas pour voir combien de mémoire l'image chargée par ʻImage utilise.
L'analyseur de mémoire Eclipse a été utilisé pour enquêter sur le vidage du tas.

La platformImage dans ʻImage` ressemble à ça, alors allez regarder à l'intérieur.

com.sum.prism.Image ressemble à ça, alors allez voir à l'intérieur.

La taille des pixels de l'image est stockée en «largeur» et «hauteur».
De plus, il semble que pixelBuffer stocke les données d'image dans un tableau d'octets, alors regardez à l'intérieur.

Cela ressemble à un bingo. «capacité» est «36366672» (environ 35 Mo). Quand je l'ai recherché, «hb» était un tableau de «byte», et il semble que toutes les données d'image aient été stockées.
Cette taille de «36 636 672» correspond exactement à la taille de «longueur x largeur x 3» dans l'image.
(4,288 * 2,848 = 12,212,224, 12,212,224 * 3 = 36,636,672)
En d'autres termes, toutes les données RVB (3 octets) de tous les pixels sont chargées.
La taille du disque est d'environ 6,5 Mo, mais une fois chargée en mémoire, elle est assez grande avec 35 Mo.
Je pense que la différence de taille entre le disque et la mémoire variera en fonction du format de compression de l'image d'origine et de la présence ou non du canal alpha (transparence).
ʻImage` vous permet de spécifier la taille de l'image et de la charger.
En utilisant cela, les images peuvent être chargées dans une taille plus petite que l'original, de sorte que la consommation de mémoire peut être réduite. Cependant, veuillez noter qu'elle ne sera pas affichée avec la même qualité que l'image d'origine car elle sera chargée dans une petite taille.
Le chargement en arrière-plan peut améliorer la vitesse d'affichage, mais vous devez également faire attention à la consommation de mémoire lors de l'utilisation du cache par préchargement.
Recommended Posts