当前位置: 首页 > 面试题库 >

JavaFx 8-相对于鼠标位置缩放/缩放ScrollPane

宦子琪
2023-03-14
问题内容

我需要在滚动窗格上相对于鼠标位置放大/缩小。

我目前通过将内容包装在一个组中并缩放组本身来实现缩放功能。我用自定义枢轴创建一个新的Scale对象。(枢轴设置为鼠标位置)

这在Group的初始比例为1.0的情况下非常适用,但是之后的缩放比例无法沿正确的方向缩放-我相信这是因为Group缩放后相对鼠标位置会发生变化。

我的代码:

@Override
public void initialize(URL location, ResourceBundle resources) {

    Delta initial_mouse_pos = new Delta();

    anchorpane.setOnScrollStarted(event -> {
        initial_mouse_pos.x = event.getX();
        initial_mouse_pos.y = event.getY();
    });

    anchorpane.setOnScroll(event -> {
        double zoom_fac = 1.05;
        double delta_y = event.getDeltaY();

        if(delta_y < 0) {
            zoom_fac = 2.0 - zoom_fac;
        }

        Scale newScale = new Scale();
        newScale.setPivotX(initial_mouse_pos.x);
        newScale.setPivotY(initial_mouse_pos.y);
        newScale.setX( content_group.getScaleX() * zoom_fac );
        newScale.setY( content_group.getScaleY() * zoom_fac );

        content_group.getTransforms().add(newScale);

        event.consume();
    });
}

private class Delta { double x, y; }

如何在不同的缩放级别上获得正确的鼠标位置?有没有一种更简单的缩放ScrollPane的完全不同的方法


问题答案:

这是一个 可扩展的,可缩放的 JavaFX ScrollPane:

import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;

public class ZoomableScrollPane extends ScrollPane {
    private double scaleValue = 0.7;
    private double zoomIntensity = 0.02;
    private Node target;
    private Node zoomNode;

    public ZoomableScrollPane(Node target) {
        super();
        this.target = target;
        this.zoomNode = new Group(target);
        setContent(outerNode(zoomNode));

        setPannable(true);
        setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        setFitToHeight(true); //center
        setFitToWidth(true); //center

        updateScale();
    }

    private Node outerNode(Node node) {
        Node outerNode = centeredNode(node);
        outerNode.setOnScroll(e -> {
            e.consume();
            onScroll(e.getTextDeltaY(), new Point2D(e.getX(), e.getY()));
        });
        return outerNode;
    }

    private Node centeredNode(Node node) {
        VBox vBox = new VBox(node);
        vBox.setAlignment(Pos.CENTER);
        return vBox;
    }

    private void updateScale() {
        target.setScaleX(scaleValue);
        target.setScaleY(scaleValue);
    }

    private void onScroll(double wheelDelta, Point2D mousePoint) {
        double zoomFactor = Math.exp(wheelDelta * zoomIntensity);

        Bounds innerBounds = zoomNode.getLayoutBounds();
        Bounds viewportBounds = getViewportBounds();

        // calculate pixel offsets from [0, 1] range
        double valX = this.getHvalue() * (innerBounds.getWidth() - viewportBounds.getWidth());
        double valY = this.getVvalue() * (innerBounds.getHeight() - viewportBounds.getHeight());

        scaleValue = scaleValue * zoomFactor;
        updateScale();
        this.layout(); // refresh ScrollPane scroll positions & target bounds

        // convert target coordinates to zoomTarget coordinates
        Point2D posInZoomTarget = target.parentToLocal(zoomNode.parentToLocal(mousePoint));

        // calculate adjustment of scroll position (pixels)
        Point2D adjustment = target.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));

        // convert back to [0, 1] range
        // (too large/small values are automatically corrected by ScrollPane)
        Bounds updatedInnerBounds = zoomNode.getBoundsInLocal();
        this.setHvalue((valX + adjustment.getX()) / (updatedInnerBounds.getWidth() - viewportBounds.getWidth()));
        this.setVvalue((valY + adjustment.getY()) / (updatedInnerBounds.getHeight() - viewportBounds.getHeight()));
    }
}


 类似资料:
  • 我需要相对于鼠标位置放大/缩小滚动窗格。 我目前通过将我的内容包装在一个组中并缩放组本身来实现缩放功能。我创建了一个带有自定义透视的新Scale对象。(枢轴设置为鼠标位置) 如何在不同级别的缩放中获得正确的鼠标位置?是否有一种完全不同的方法来缩放滚动窗格更容易?

  • 有什么想法吗?提前谢了。

  • 目前我正在使用glOrtho来缩放和平移我正在渲染的2D图形。 我已经将视窗设置为标准的宽度和高度。然后,我设置glOrtho,使我的平截头体使屏幕坐标匹配世界坐标。 当我在鼠标回调中执行缩放功能时,我将截头体边缘乘以缩放因子。。。。 我的问题是……如何使用鼠标位置作为中心进行缩放? 我尝试过这个…(其中mouseStoreX和mousestrey是第一次单击时存储的位置) 它似乎工作,但当我做一

  • 问题内容: 我需要实现变焦为包含在。我已经通过覆盖方法和调用来成功进行缩放。 这是不正常:对的和的规模如预期,但一定会得到的和这样的寄存器在预分频的位置。我能做什么?感谢您的阅读。 问题答案: 显示了如何使用明确的转化方法扩展鼠标坐标:,,和。)。

  • 我尝试了另一篇文章中给出的这个例子,以了解关于相对于鼠标指针的缩放和平移。当所有东西都在网格上时,缩放就像预期的那样工作: 当缩放到左上角图像上的鼠标指针位置时,它将缩放到右上角图像中所见的准确位置。 如果某物被拖出网格,例如,枢轴开始“行为不端”:

  • 我正在制作的游戏把所有东西都放在pygame.surface上,然后按用户显示器的大小缩放,保持宽高比,然后再把表面放在主屏幕上。我现在遇到的问题是,当我查询鼠标位置时(因为我想对某些精灵做悬停效果),它离精灵的位置很远,但是x和y匹配精灵的坐标。这是因为我爬上了表面吗?如果是这样,是否有一个内置的PyGame方法将鼠标分配到不同的表面?还是我必须写一个算法来转换这些弦?