JavaFx缩放和平移具有覆盖固定比例标签的图像

2022-01-29 09:55:10 标签 javajavafxpanning

我是一所大学的一名医生,我正在开发x射线分析软件,其中用户定义解剖点与小圆圈放置在x射线图像。到目前为止,我很满意,但我需要根据鼠标位置使用鼠标滚轮实现缩放和平移。

我简化了我的代码,以清楚原来的一个比这复杂得多。

在这个算法中,当缩放和平移时,点不应该根据图像移动,因此它们的位置保持不变,在缩放时,点附近的标签必须保持相同的字体大小(我们不想看到巨大的标签)。我被困在这一点上了。

请帮忙生成这个算法?

下面是一个例子:

下面是我的java代码:

package main.java;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Circle;    
public class ZoomClass {
    @FXML
    AnchorPane xRayAnchorPane;
    @FXML
    ImageView xRayImage;
    @FXML
    ScrollPane xRayScrollPane;
    @FXML
    Label pointsLabel;    
    public void initialize() {    
        xRayImage.setOnMouseClicked(mouseEvent ->
        {
            if(mouseEvent.getButton().equals(MouseButton.PRIMARY)) // ADD POINTS
            {
                Circle circle = new Circle();
                circle.setCenterX(mouseEvent.getX()+58);   // Some Offset values to proper positioning
                circle.setCenterY(mouseEvent.getY()+75);   // Some Offset values to proper positioning
                circle.setRadius(2);
                xRayAnchorPane.getChildren().add(circle);  // Adding circle to mainFrame
                pointsLabel.setText("A");     // Defining the point's name
                pointsLabel.setLayoutX(circle.getCenterX()+5);  // Some Offset values to proper positioning
                pointsLabel.setLayoutY(circle.getCenterY());  // Some Offset values to proper positioning
            }
        });
    }
}

我的FXML文件:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="650.0" prefWidth="851.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.ZoomClass" fx:id="xRayAnchorPane">
   <children>
      <ScrollPane layoutX="56.0" layoutY="71.0" prefHeight="533.0" prefWidth="743.0" fx:id="xRayScrollPane">
         <content>
            <ImageView fitHeight="736.0" fitWidth="739.0" pickOnBounds="true" preserveRatio="true" fx:id="xRayImage">
               <image>
                  <Image url="@ceph2.jpg" />
               </image>
            </ImageView>
         </content>
      </ScrollPane>
      <Label fx:id="pointsLabel" layoutX="14.0" layoutY="138.0" />
   </children>
</AnchorPane>

###根据这个问题,你需要为你想要放大的元素创建一个组元素。当你创建新的圆圈时,你应该添加到缩放组。最后,对创建的组元素应用zoom

# # #这有帮助吗?

缩放因子只能在ImageView上通过使用鼠标滚轮并按下CTRL键来设置。

标签被放置在ScrollPane之外的锚窗格中,因此它们不受你需要的平移和缩放的影响。

package com.stackoverflow.zoom;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.ZoomEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Zoomer extends Application {
    private AnchorPane ap;
    private ImageView imgView;
    private char markTxt = 'A';
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        ap = new AnchorPane();
        Image img = new Image("https://upload.wikimedia.org/wikipedia/commons/d/dc/Medical_X-Ray_imaging_SEQ07_nevit.jpg");
        imgView = new ImageView(img);
        ScrollPane sp = new ScrollPane(imgView);
        AnchorPane.setTopAnchor(sp, 0.0);
        AnchorPane.setLeftAnchor(sp, 0.0);
        AnchorPane.setBottomAnchor(sp, 0.0);
        AnchorPane.setRightAnchor(sp, 0.0);
        ap.getChildren().add(sp);
        imgView.setOnMouseClicked(this::onClick);
        imgView.setOnScroll(this::imageScrolled);
        Scene scene = new Scene(ap);
        primaryStage.setTitle("Zoom Image");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public void onClick(MouseEvent event) {
        if (event.getButton() == MouseButton.PRIMARY) {
            placeMarker(event.getSceneX(), event.getSceneY());
        }
    }
    private void imageScrolled(ScrollEvent event) {
        // When holding CTRL mouse wheel will be used for zooming
        if (event.isControlDown()) {
            double delta = event.getDeltaY();
            double adjust = delta / 1000.0;
            double zoom = Math.min(10, Math.max(0.1, imgView.getScaleX() + adjust));
            setImageZoom(zoom);
            event.consume();
        }
    }
    private void placeMarker(double sceneX, double sceneY) {
        Circle circle = new Circle(2);
        circle.setStroke(Color.RED);
        circle.setTranslateY(-12);
        Label marker = new Label(String.valueOf(markTxt), circle);
        marker.setTextFill(Color.RED);
        markTxt++;
        Point2D p = ap.sceneToLocal(sceneX, sceneY);
        AnchorPane.setTopAnchor(marker, p.getY());
        AnchorPane.setLeftAnchor(marker, p.getX());
        ap.getChildren().add(marker);
    }
    private void setImageZoom(double factor) {
        imgView.setScaleX(factor);
        imgView.setScaleY(factor);
    }
}
阅读全文

▼ 版权说明

相关文章也很精彩
推荐内容
更多标签
相关热门
全站排行
随便看看

错说 cuoshuo.com —— 程序员的报错记录

部分内容根据CC版权协议转载;网站内容仅供参考,生产环境使用务必查阅官方文档

辽ICP备19011660号-5

×

扫码关注公众号:职场神器
发送: 1
获取永久解锁本站全部文章的验证码