package net.thirdy.blackmarket.samples; import javafx.application.Application; import javafx.beans.property.*; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ScrollPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; /** demonstrates various ways to fill a constrained region with an image */ public class ImageFill extends Application { private static final String FX_EXPERIENCE_LOGO_URL = "http://fxexperience.com/wp-content/uploads/2010/06/logo.png"; final ObjectProperty<Image> poster = new SimpleObjectProperty<Image>(new Image(FX_EXPERIENCE_LOGO_URL)); public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { // create a pane which constrain the size of the displayed image. StackPane constrainingPane = new StackPane(); // just placing the image in the constraining pane will make the constrainingpane go above it's max size. // constrainingPane.getChildren().add(new ImageView(poster.get())); // to get around this, you could embed the image in a scrollpane. // constrainingPane.getChildren().add(getScrollPane(poster)); // or perhaps preferably, you could use a slightly customized standard pane // and style it's background to display the image. constrainingPane.getChildren().add( new ImagePane(FX_EXPERIENCE_LOGO_URL, "-fx-background-size: contain; -fx-background-repeat: no-repeat;") ); constrainingPane.setStyle("-fx-border-color: red; -fx-border-width: 1; -fx-border-insets: -2;"); // layout the scene. StackPane layout = new StackPane(); layout.getChildren().add(constrainingPane); layout.setStyle("-fx-background-color: whitesmoke;"); Scene scene = new Scene(layout, 800, 600); // clamp the pane to the scene size. constrainingPane.maxWidthProperty().bind(scene.widthProperty().divide(2)); constrainingPane.minWidthProperty().bind(scene.widthProperty().divide(2)); constrainingPane.maxHeightProperty().bind(scene.heightProperty().divide(2)); constrainingPane.minHeightProperty().bind(scene.heightProperty().divide(2)); // show the scene. primaryStage.setScene(scene); primaryStage.show(); } // size a replaceable image by placing it in a scrollpane. private Node getScrollPane(final ObjectProperty<Image> poster) { return new ScrollPane() {{ final ReadOnlyDoubleProperty widthProperty = widthProperty(); final ReadOnlyDoubleProperty heightProperty = heightProperty(); setHbarPolicy(ScrollBarPolicy.NEVER); setVbarPolicy(ScrollBarPolicy.NEVER); setContent(new ImageView() {{ imageProperty().bind(poster); setPreserveRatio(true); setSmooth(true); fitWidthProperty().bind(widthProperty); fitHeightProperty().bind(heightProperty); }}); }}; } } /** A pane with an image background */ class ImagePane extends Pane { // size an image by placing it in a pane. ImagePane(String imageLoc) { this(imageLoc, "-fx-background-size: cover; -fx-background-repeat: no-repeat;"); } // size an image by placing it in a pane. ImagePane(String imageLoc, String style) { this(new SimpleStringProperty(imageLoc), new SimpleStringProperty(style)); } // size a replacable image in a pane and add a replaceable style. ImagePane(StringProperty imageLocProperty, StringProperty styleProperty) { styleProperty().bind( new SimpleStringProperty("-fx-background-image: url(\"") .concat(imageLocProperty) .concat(new SimpleStringProperty("\");")) .concat(styleProperty) ); } }