简体   繁体   中英

javafx - access height and width values of an image after it is resized to preserve aspect ratio

Hello all and thanks for reading. I am currently building an image annotation tool. Images are loaded into and bound to the parent container(borderpane). Aspect ratio is also preserved. The code snippet attached illustrates these points.

     imageView.setPreserveRatio(true);
     imageView.setSmooth(true);
     imageView.fitHeightProperty().bind(heightProperty());
     imageView.fitWidthProperty().bind(widthProperty());

This works fine: images fit the window and are resized when the window is resized.

On top of this I have placed a canvas on which the user can draw rectangles. After they have drawn a rectangle, a pop up is launched in which they can write an annotation. After it is saved the user can hover over the drawn rectangle and the annotation will appear.

I want to know if it's possible to access the height and width values of an image after it has been resized to fit the window and while it is being resized when the window is being resized.

My reason for needing this is that I want the canvas to mirror the dimensions of the image so that the annotations are within its bounds. Currently when the window is resized the annotations do not remain 'fixed' to their area as the canvas is set to the dimensions of the window and not the image.

Any help would be greatly appreciated. I've hit a bit of a wall. And am not even sure if what I'm asking is possible in JavaFX. Thanks again for reading.

Evening all. Here's how I managed to solve my problem for anyone who might need help with a similar issue in the future.

First, create a 'Resizable Canvas' using this code:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;  

class ResizableCanvas extends Canvas {

        public ResizableCanvas() {

            // Redraw canvas when size changes.

            widthProperty().addListener(evt -> draw());

            heightProperty().addListener(evt -> draw());

        }

        private void draw() {

            double width = getWidth();

            double height = getHeight();

            GraphicsContext gc = getGraphicsContext2D();

            gc.clearRect(0, 0, width, height);

            gc.setStroke(Color.RED);

            gc.strokeLine(0, 0, width, height);

            gc.strokeLine(0, height, width, 0);
        }
    @Override

        public boolean isResizable() {

            return true;
        }


    @Override

        public double prefWidth(double height) {

            return getWidth();

        }

        @Override

        public double prefHeight(double width) {

            return getHeight();

        }

    }

This done, set up your Stage as follows:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;


public class ImageViewTest extends Application   {

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

@Override
public void start(Stage stage) throws Exception {

    ResizableCanvas rc = new ResizableCanvas();
    rc.setOnMouseEntered(e -> {
        System.out.println("entered ");
    });
    Image image = new Image("rushmore.png");

    ImageView imageView = new ImageView();
    imageView.setImage(image);
    imageView.setSmooth(true);
    imageView.setCache(true);


    AnchorPane rootAnchorPane = new AnchorPane();
    AnchorPane resizableCanvasAnchorPane = new AnchorPane();


   rc.widthProperty().bind(resizableCanvasAnchorPane.widthProperty());
 rc.heightProperty().bind(resizableCanvasAnchorPane.heightProperty());


    imageView.fitWidthProperty().bind(stage.widthProperty());
    imageView.fitHeightProperty().bind(stage.heightProperty());
    imageView.setPreserveRatio(true);

    //here's where the 'magic happens'
    resizableCanvasAnchorPane.getChildren().addAll(imageView, rc);
    rootAnchorPane.getChildren().addAll(resizableCanvasAnchorPane,rc);

    Scene scene = new Scene(rootAnchorPane);
    scene.setFill(Color.BLACK);
    stage.setTitle("ImageView Test");
    stage.setWidth(415);
    stage.setHeight(200);
    stage.setScene(scene);
    stage.show(); 
   }

}

Big thanks also goes to Dirk Lemmermann and this tutorial:

https://www.javacodegeeks.com/2014/04/javafx-tip-1-resizable-canvas.html

Hopefully you can see that the canvas resizes with the image. There are red guidelines over the image and a mouse event to illustrate this. Check the console of your IDE and you can see an event being fired when the mouse is within the bounds of the canvas.

Any questions, let me know.

Cheers!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM