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.
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.
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.
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);
}
}
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.
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());
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.
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.
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.
Das platformImage
im Image
sieht so aus, also schau hinein.
com.sum.prism.Image
sieht so aus, also schau hinein.
Die Pixelgröße des Bildes wird in "Breite" und "Höhe" gespeichert. Darüber hinaus scheint "pixelBuffer" Bilddaten in einem Byte-Array zu speichern.
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.
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.
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