Issue
I am developing a tracing program by placing dots to anatomical points on Xray. My problem is, I'm trying to zoom into my X-ray image (Imageview
) while my mouse hovering onto it and displaying in another Imageview
. I want my mouse to create a virtual rectangle around it and stays at the center while moving and transfers that live image to other small Imageview
, I've done this so far but there are some glitches. My rectangle does not follow my mouse exactly as it should, and the glitch accelerates when I move into corners, What can you suggest? I'm sharing my error and my codes to clarify all those things.
Maybe I should create a rectangle shape and place it around mouse position and crop the image live, fit into the zoomedImageview
, and display all the time, but I am stuck in this.
The main problem is, mouse position and center of zoomedImageview
's center position has to coincide all the time.
Xray Imageview Fitwidth-height is 800x800 zoomedImageview Fitwidth-height is 250x250
public class DrawingController {
@FXML
ImageView xrayImage;
@FXML
ImageView zoomedImage;
public void initialize()
{
xrayImage.setOnMouseMoved(e -> { //HOVERING ON XRAY
PixelReader reader = XrayImageview.getImage().getPixelReader();
WritableImage newImage = new WritableImage(reader,
(int) e.getX(), //x and y is picked according to hovering mouse position
(int) e.getY(),
(int) 250, // 250x250 rectangle is requested.
(int) 250);
zoomedImage.setImage(newImage); // Displaying zoomed image
});
}}
And My FXML file is:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="913.0" prefWidth="1238.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.controllers.DrawingController">
<children>
<ImageView fitHeight="800.0" fitWidth="800.0" layoutX="418.0" layoutY="33.0" pickOnBounds="true" preserveRatio="true" fx:id="xrayImage">
<image>
<Image url="@threatCare.png" />
</image>
</ImageView>
<ImageView fx:id="zoomedImage" fitHeight="250.0" fitWidth="250.0" layoutX="108.0" layoutY="433.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
And the Main class :
package main.java;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import main.java.database.DatabaseCreator;
import javax.swing.text.html.ImageView;
import java.awt.*;
public class Runner extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("../resources/DrawingPanel.fxml"));
primaryStage.setTitle("TreatCare Software Systems");
Scene scene = new Scene(root,1200,950);
primaryStage.setScene(scene);
primaryStage.setMinWidth(1200);
primaryStage.setMinHeight(950);
primaryStage.setMaximized(true);
primaryStage.setOnCloseRequest( e -> SystemClose());
primaryStage.show();
}
private void SystemClose(){
System.exit(0);
}
public static void main(String[] args){
launch(args);
}
}
Solution
You are scaling your image, so you need to convert your mouse coordinates according to that scaling.
From your .fxml file:
<ImageView fitHeight="800.0" fitWidth="800.0" layoutX="418.0" layoutY="33.0" pickOnBounds="true" preserveRatio="true" fx:id="xrayImage">
There are three attributes in that line which scale the image:
fitWidth="800.0"
- scales image to 800 pixels widefitHeight="800.0"
- scales image to 800 pixels highpreserveRatio="true"
- overrides all scaling so image always has the same scale in both dimensions
So you need to multiply your mouse coordinates according to those:
xrayImage.setOnMouseMoved(e -> { //HOVERING ON XRAY
Image image = xrayImage.getImage();
double x = e.getX();
double y = e.getY();
double xScale = (xrayImage.getFitWidth() > 0 ?
image.getWidth() / xrayImage.getFitWidth() : 1);
double yScale = (xrayImage.getFitHeight() > 0 ?
image.getHeight() / xrayImage.getFitHeight() : 1);
if (xrayImage.isPreserveRatio()) {
double scale = Math.max(xScale, yScale);
x *= scale;
y *= scale;
} else {
x *= xScale;
y *= yScale;
}
x = Math.max(0, x - 125);
y = Math.max(0, y - 125);
double width = Math.min(image.getWidth() - x, 250);
double height = Math.min(image.getHeight() - y, 250);
PixelReader reader = image.getPixelReader();
WritableImage newImage = new WritableImage(reader,
(int) x, (int) y, (int) width, (int) height);
zoomedImage.setImage(newImage); // Displaying zoomed image
});
Answered By - VGR
Answer Checked By - Timothy Miller (JavaFixing Admin)