Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fill an image in an imageView in javafx?

Tags:

java

javafx

I have an image saved in my database that is passed to an image as a byte array and then loaded to the Image view. However, I can't get it to fill the imageView. I use the following code:

package com.example.AppPrototipo.ui.tourist;

imports...

@Component
public class ExperienceController {

    @FXML
    Pane imagePane;

    @FXML
    ImageView imageViewPrincipal;

    private final ExperienceRepository experienceRepository;

    public ExperienceController(ExperienceRepository experienceRepository) {
        this.experienceRepository = experienceRepository;
    }

    @FXML
    private void initialize(){

        Experience experience = experienceRepository.findById(1);

        Image image = new Image(new ByteArrayInputStream(experience.getImages().get(0).getImageData()));
        imageViewPrincipal.setImage(image);
        imageViewPrincipal.fitWidthProperty().bind(imagePane.widthProperty());
        imageViewPrincipal.fitHeightProperty().bind(imagePane.heightProperty());


    }
}

This is the result i get: Image in imageView but not filling the right side

The desired result would be that the image fills the whole width (fill the black side) by cropping the top and bottom sides and remaining centered. Would anyone be able to help me?

like image 385
Juan Cruz Carrau Avatar asked Oct 24 '25 04:10

Juan Cruz Carrau


1 Answers

Assuming you're setting the preserveRatio property to true on the ImageView, and as matt stated is his comment, you only need to set one of them, say fitWidth, and the fitHeight will be calculated using the image ratio.

the problem is that the ratios of the image and the pane don't match so you need to do some cropping using setViewport, and it would be best to do the cropping when the pane's height or width change.

What you need to do is to calculate the ratio of the image, and compare it to the ratio of the pane, the comparison will let you decide whether to keep the original width or original height of the image, and you'll calculate the other using the pane's ratio.

Not really sure if that's the best practice but here's the code for what i have described

    double oldImageWidth = image.getWidth(), oldImageHeight = image.getHeight();            //saving the original image size and ratio
    double imageRatio = oldImageWidth / oldImageHeight;

    imageViewPrincipal.setImage(image);

    ChangeListener<Number> listener = (obs, ov, nv) -> {
        double paneWidth = imagePane.getWidth();
        double paneHeight = imagePane.getHeight();

        double paneRatio = paneWidth / paneHeight;                                          //calculating the new pane's ratio 
                                                                                            //after width or height changed
        double newImageWidth = oldImageWidth, newImageHeight = oldImageHeight;
        
        if (paneRatio > imageRatio) {
            newImageHeight = oldImageWidth / paneRatio;
        } else if (paneRatio < imageRatio) {
            newImageWidth = oldImageHeight * paneRatio;
        }
        
        imageViewPrincipal.setViewport(new Rectangle2D(                                     // The rectangle used to crop
                (oldImageWidth - newImageWidth) / 2, (oldImageHeight - newImageHeight) / 2, //MinX and MinY to crop from the center
                newImageWidth, newImageHeight)                                              // new width and height
            );
        
        imageViewPrincipal.setFitWidth(paneWidth);
    };

    imagePane.widthProperty().addListener(listener);
    imagePane.heightProperty().addListener(listener);

And here is how it looks

screenshot

like image 72
SDIDSA Avatar answered Oct 25 '25 16:10

SDIDSA



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!