Son dos clases: Image, que es la imagen en memoria, e ImageView, que es el nodo que la dibuja. Separarlas permite mostrar la misma imagen en varios sitios sin cargarla dos veces.
También te puede interesar
package javafx.application does not exist, no es que esté mal: es que faltan los módulos. Con Maven o Gradle se añaden como dependencia; a mano, se bajan y se pasan en el module path.El ejemplo completo
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class VerImagen extends Application {
@Override
public void start(Stage ventana) {
Image imagen = new Image("file:duke.png");
ImageView vista = new ImageView(imagen);
vista.setFitHeight(220);
vista.setPreserveRatio(true);
vista.setSmooth(true);
Label pie = new Label((int) imagen.getWidth() + " x " + (int) imagen.getHeight() + " px");
VBox raiz = new VBox(10, vista, pie);
raiz.setAlignment(Pos.CENTER);
raiz.setPadding(new Insets(16));
ventana.setTitle("Ver imagen");
ventana.setScene(new Scene(raiz, 300, 320));
ventana.show();
}
public static void main(String[] args) { launch(args); }
}
De dónde se puede cargar
new Image("file:duke.png"); // ruta relativa en el disco
new Image("file:/home/ana/fotos/duke.png"); // ruta absoluta
new Image("https://decodigo.com/logo.png"); // por red
new Image(VerImagen.class.getResourceAsStream("/duke.png")); // dentro del jar.jar y ya no hay tal archivo. Si getResourceAsStream devuelve null, la ruta está mal: tiene que empezar por / y colgar de src/main/resources.Escalar sin deformar
vista.setFitHeight(220); vista.setPreserveRatio(true); vista.setSmooth(true);
Las tres juntas. Si pones setFitWidth y setFitHeight sin preserveRatio, la imagen se estira. Con preserveRatio, el valor que pongas es un máximo y el otro se calcula. Y setSmooth usa un algoritmo mejor al reducir: cuesta un poco más y se nota bastante.
Escalar en el ImageView no ahorra memoria: la imagen sigue cargada a su tamaño original. Para eso se escala al cargar:
Image miniatura = new Image("file:foto-grande.jpg", 200, 0, true, true);
// ancho ↑ alto ↑ ratio ↑ suave ↑Con el alto a 0 y el ratio a true, calcula el alto solo. Para una galería de miniaturas, la diferencia entre cargar a 200 píxeles o cargar a 4000 es de varios cientos de megabytes.
Que no se congele la ventana
Image imagen = new Image("https://ejemplo.com/foto-grande.jpg", true); // en segundo plano
vista.setImage(imagen);
imagen.progressProperty().addListener((o, v, n) -> barra.setProgress(n.doubleValue()));
imagen.errorProperty().addListener((o, v, hayError) -> {
if (hayError) etiqueta.setText("no se pudo cargar");
});Ese true del final es backgroundLoading: la llamada vuelve en el acto y la imagen se va pintando cuando llega. Sin él, una imagen por red bloquea la interfaz hasta que termine la descarga.
backgroundLoading, getWidth() devuelve 0 mientras la imagen no haya llegado, y una carga fallida no lanza ninguna excepción: hay que mirar isError() o suscribirse a errorProperty.| Para… | Usa |
|---|---|
| Mostrarla | new ImageView(imagen) |
| Que quepa sin deformarse | setFitHeight + setPreserveRatio(true) |
| Que no ocupe memoria de más | pasar el tamaño al constructor de Image |
| Que no bloquee | el cuarto parámetro backgroundLoading a true |
| Empaquetarla en el jar | getResourceAsStream("/imagen.png") |
| Recortarla | vista.setViewport(new Rectangle2D(x, y, ancho, alto)) |
Más información en inglés: Display an image in JavaFX.
Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.