JavaFX-Bild im Hintergrund laden

Der Standard wird synchron geladen

Wenn eine Instanz von "Image" normal erstellt wird, werden die Bilder synchron geladen (es wird keine Verarbeitung zurückgegeben, bis das Laden abgeschlossen ist).

Wenn das Bild klein ist, gibt es kein besonderes Problem. Wenn jedoch ein großes Bild angezeigt wird, wird die Verarbeitung für eine Weile angehalten, was die Bedienbarkeit beeinträchtigen kann.

Laden Sie im Hintergrund

Um ein Bild in der Instanz "Image" im Hintergrund zu laden, geben Sie "true" für das Konstruktorargument "backgroundLoading" an. Es gibt zwei Konstruktoren, die "backgroundLoading" angeben können.

Wenn Sie eine Instanz mit "true" für "backgroundLoading" erstellen, wird das Bild asynchron geladen. Dadurch kann der Prozess ohne Unterbrechung fortgesetzt werden.

Ladevorgang anzeigen

Wenn Sie das Laden einfach in den Hintergrund stellen, wird das Bild erst angezeigt, wenn das Laden abgeschlossen ist.

Wenn die Größe groß ist und das Laden lange dauert, kann die Tatsache, dass kein Bild angezeigt wird, den Benutzer stören. Daher kann es sinnvoll sein, den Fortschritt des Ladens mit einem Fortschrittsbalken oder dergleichen anzuzeigen.

Die Klasse "Image" kann den Fortschritt des Ladens [progress] kennen (https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/image/Image.html#progressProperty). Immobilien anbieten. Wenn Sie dies verwenden, können Sie den Ladevorgang relativ einfach anzeigen.

Implementierung

WS000000.jpg

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

Ausführungsergebnis

javafx.gif

Es ist etwas schnell und verwirrend, aber der Fortschrittsbalken wird angezeigt, während das Bild geladen wird, und das Bild wird angezeigt, wenn das Laden abgeschlossen ist.

Erläuterung

WS000000.jpg

MainController.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));

MainController.java


        Image image = new Image(Paths.get("./image/shirakawago.jpg ").toUri().toString(), true);
        progressBar.progressProperty().bind(image.progressProperty());

Im Voraus laden

verdienen

Das Laden im Hintergrund kann nicht nur durch Laden des aktuell angezeigten Bildes, sondern auch durch Vorladen des als Nächstes anzuzeigenden Bilds verwendet werden.

In diesem Fall wird nur die "Image" -Instanz hinter den Kulissen generiert, und beim Wechseln von Bildern wird die "Image" -Instanz durch "setImage ()" der "ImageView" ersetzt.

Bild


@FXML
private ImageView imageView;
private Image nextImage;

public void initialize(URL location, ResourceBundle resources) {
    //Laden Sie das nächste Bild in den Hintergrund
    nextImage = new Image("next-image.jpg ", true);

    Image initialImage = new Image("initial-image.jpg ", true);
    imageView.setImage(initialImage);
}

@FXML
public void nextPage() {
    //Stellen Sie das nächste geladene Bild ein
    imageView.setImage(nextImage);
}

Selbst schwere Bilder können schnell angezeigt werden, indem sie im Voraus geladen werden, was zu einer Verbesserung der Bedienbarkeit führen kann.

Speichernutzung

Es ist zu beachten, dass das Vorladen die Anzeigegeschwindigkeit verbessern kann, jedoch auf Kosten eines erhöhten Speicherverbrauchs.

Insbesondere sollte beachtet werden, dass es einen großen Unterschied zwischen der Größe des Images auf der Festplatte und der Größe beim Laden in den Speicher gibt.

Ich werde untersuchen, wie unterschiedlich es tatsächlich ist.

javafx.jpg

Hier ist die Größe auf der Festplatte, ca. 6,5 MB.

Laden Sie dieses Bild mit Image und machen Sie dann einen Heap-Dump, um zu sehen, wie viel Speicher das von Image geladene Bild verwendet. Der Eclipse Memory Analyzer wurde verwendet, um den Heap-Dump zu untersuchen.


javafx.jpg

Das platformImage im Image sieht so aus, also schau hinein.


javafx.jpg

com.sum.prism.Image sieht so aus, also schau hinein.


javafx.jpg

Die Pixelgröße des Bildes wird in "Breite" und "Höhe" gespeichert. Darüber hinaus scheint "pixelBuffer" Bilddaten in einem Byte-Array zu speichern.


javafx.jpg

Es sieht aus wie ein Bingo. "Kapazität" ist "36366672" (ca. 35 MB). Als ich es nachgeschlagen habe, war "hb" ein Array von "Byte", und es scheint, dass alle Bilddaten gespeichert wurden.

Diese Größe von "36.636.672" entspricht genau der Größe von "Länge x Breite x 3" im Bild. (4,288 * 2,848 = 12,212,224, 12,212,224 * 3 = 36,636,672

Mit anderen Worten werden alle RGB-Daten (3 Byte) aller Pixel geladen.

Die Größe der Festplatte beträgt ungefähr 6,5 MB, aber wenn sie in den Speicher geladen wird, ist sie mit 35 MB ziemlich groß.

Ich denke, dass der Größenunterschied zwischen der Disc und dem Speicher abhängig vom Komprimierungsformat des Originalbilds und dem Vorhandensein oder Fehlen des Alphakanals (Transparenz) variieren wird.

Reduzieren Sie die Größe und Last

Image kann durch Angabe der Bildgröße geladen werden.

Auf diese Weise können Bilder in einer kleineren Größe als das Original geladen werden, sodass der Speicherverbrauch reduziert werden kann. Beachten Sie jedoch, dass es nicht in der gleichen Qualität wie das Originalbild angezeigt wird, da es in einer kleinen Größe geladen wird.

Zusammenfassung

Das Laden im Hintergrund kann die Anzeigegeschwindigkeit verbessern. Sie sollten jedoch auch den Speicherverbrauch berücksichtigen, wenn Sie den Cache durch Vorladen verwenden.

Recommended Posts

JavaFX-Bild im Hintergrund laden
Rails6: Extrahieren Sie das Bild im Aktionstext
Fügen Sie das von http erhaltene Bild in NotificationCompat ein
Hintergrundbildtransparenz (Überlagern des Bildes mit Ihrer Lieblingsfarbe)
[Rails 6] So legen Sie ein Hintergrundbild in Rails [CSS] fest
[Schienen] So zeigen Sie Bilder in der Ansicht an
Installieren Sie das Garn im Docker-Image
Installieren Sie das Plug-In in Eclipse
Java legt die Hintergrundfarbe und das Hintergrundbild für PowerPoint-Dokumente fest
[Android Studio] Legen Sie ein beliebiges Bild für den Anwendungshintergrund fest. [Java]
Ersetzen Sie die Vorschau durch Hochladen, indem Sie auf das Bild in file_field of Rails klicken
Greifen Sie mit Java auf die Netzwerkschnittstelle zu
Errate den Zeichencode in Java
Ausnahmen im AWS SDK
Übergeben Sie das Gebietsschema i18n an JavaScript
Apache Camel in der Cloud-Ära
Über das Symbol <%%> in Rails erb
Geben Sie den Java-Speicherort in eclipse.ini an
Lassen Sie uns den Bildsuchfilter überprüfen
Scrollen Sie automatisch mit libGDX durch den Hintergrund
Entpacken Sie die Zip-Datei in Java
Verwenden Sie das Findbugs-Plugin in Eclipse
Mit CSS in die Mitte legen
Analysieren der COTOHA-API-Syntaxanalyse in Java
Fügen Sie Bildressourcen in die JAR-Datei ein
Ja, lassen Sie uns eine Vorschau des Bildes anzeigen. ~ part5 ~
Reihenfolge der Verarbeitung im Programm
Was sind die Regeln in JUnit?
Bildverarbeitung: Spielen wir mit dem Bild
Rufen Sie die Super-Methode in Java auf
Was tun, wenn das Hintergrundbild nach der Bereitstellung nicht angewendet wird?
[Schienen] Über den Fehler, dass das Bild nicht in der Produktionsumgebung angezeigt wird
Ändern Sie das Speicherziel des Bildes in der Rails-App in S3. Teil 2