rbs
rbs

Reputation: 1167

Resizing images to fit the parent node

How do I get an image in an ImageView to automatically resize such that it always fits the parent node?

Here is a small code example:

@Override
public void start(Stage stage) throws Exception {
    BorderPane pane = new BorderPane();
    ImageView img = new ImageView("http://...");

    //didn't work for me:
    //img.fitWidthProperty().bind(new SimpleDoubleProperty(stage.getWidth())); 

    pane.setCenter(img);

    Scene scene = new Scene(pane);
    stage.setScene(scene);
    stage.show();
}

Upvotes: 42

Views: 71826

Answers (6)

Vasil Valchev
Vasil Valchev

Reputation: 5819

Fill the parent whit aspect ration, this fix the problem whit when parent height and width are not in proper ration like the image.

Image image = new Image(getClass().getResource(%path%).toString());
double ratio = image.getWidth() / image.getHeight();
double width = stage.getScene().getWidth();

ImageView imageView.setImage(image);
imageView.setFitWidth(width);
imageView.setFitHeight(width/ratio);
imageView.setPreserveRatio(true);

Upvotes: 0

user8356718
user8356718

Reputation:

This is a calculated width method that removes the width of the scroll bar.

first:
myImageView.setPreserveRatio(true);

monitor scrollbar width changes:

scrollPane.widthProperty().addListener((observable, oldValue, newValue) -> {
            myImageView.setFitWidth(newValue.doubleValue() - (oldValue.doubleValue() - scrollPane.getViewportBounds().getWidth()));
        });

scrollBar width:
oldValue.doubleValue() - scrollPane.getViewportBounds().getWidth()

How do I set init width?
after primaryStage.show();

myImageView.setFitWidth(scrollPane.getViewportBounds().getWidth());

Upvotes: 1

dew
dew

Reputation: 31

If you want the ImageView to fit inside a windows frame, use this line of code: imageView.fitWidthProperty().bind(scene.widthProperty()).

Note that I am using widthProperty of the scene not the stage. Example:

import java.io.FileNotFoundException;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class MapViewer extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws FileNotFoundException {
        String strTitle = "Titulo de la Ventana";
        int w_width = 800;
        int w_height = 412;
        primaryStage.setTitle(strTitle);
        primaryStage.setWidth(w_width);
        primaryStage.setHeight(w_height);

        Group root = new Group();
        Scene scene = new Scene(root);

        final ImageView imv = new ImageView("file:C:/Users/utp/Documents/1.2008.png");
        imv.fitWidthProperty().bind(scene.widthProperty());
        imv.setPreserveRatio(true);

        root.getChildren().add(imv);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

}

The aspect radio of the stage (primaryStage) should be similar to that of the image (1.2008.png)

Upvotes: 2

user458577
user458577

Reputation:

This is a better solution than binding the width property (better because often when binding a child to its container, it might not be possible to make the container smaller. At other ocasions the container might even automatically start growing).

The solution below relies on overriding an ImageView so that we can let it behave as 'resizable' and then providing implementations for the minimum ,preferred, and maximum width/heights. Also important is to actually implement the resize() call.

class WrappedImageView extends ImageView
{
    WrappedImageView()
    {
        setPreserveRatio(false);
    }

    @Override
    public double minWidth(double height)
    {
        return 40;
    }

    @Override
    public double prefWidth(double height)
    {
        Image I=getImage();
        if (I==null) return minWidth(height);
        return I.getWidth();
    }

    @Override
    public double maxWidth(double height)
    {
        return 16384;
    }

    @Override
    public double minHeight(double width)
    {
        return 40;
    }

    @Override
    public double prefHeight(double width)
    {
        Image I=getImage();
        if (I==null) return minHeight(width);
        return I.getHeight();
    }

    @Override
    public double maxHeight(double width)
    {
        return 16384;
    }

    @Override
    public boolean isResizable()
    {
        return true;
    }

    @Override
    public void resize(double width, double height)
    {
        setFitWidth(width);
        setFitHeight(height);
    }
}

Upvotes: 17

Akshay Goyal
Akshay Goyal

Reputation: 61

Use ScrollPane or simply Pane to overcome this problem: Example:

 img_view1.fitWidthProperty().bind(scrollpane_imageview1.widthProperty()); 
 img_view1.fitHeightProperty().bind(scrollpane_imageview1.heightProperty());

Upvotes: 5

The Unfun Cat
The Unfun Cat

Reputation: 31898

@Override
public void start(Stage stage) throws Exception {
    BorderPane pane = new BorderPane();
    ImageView img = new ImageView("http://...");

    img.fitWidthProperty().bind(stage.widthProperty()); 

    pane.setCenter(img);

    Scene scene = new Scene(pane);
    stage.setScene(scene);
    stage.show();
}

Upvotes: 66

Related Questions