在JavaFX中使用自定义ScrollPane缩放ImageView时出现空白

问题描述 投票:0回答:1

我正在 JavaFX 中开发一个图像处理应用程序,其中涉及使用触摸板手势缩放图像。为了实现这一目标,我创建了

ScrollPane
的自定义实现,它可以使用熟悉的手势处理图像滚动和缩放。我已经包含了相关的代码片段和场景的 FXML 配置。

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

    public ZoomableScrollPane() {
        super();
    }

    public void setTarget(Node target) {
        this.target = target;
        this.zoomNode = new Group(target);
        setContent(outerNode(zoomNode));

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

        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();

        double valX = this.getHvalue() * (innerBounds.getWidth() - viewportBounds.getWidth());
        double valY = this.getVvalue() * (innerBounds.getHeight() - viewportBounds.getHeight());

        scaleValue = scaleValue * zoomFactor;
        updateScale();
        this.layout();

        Point2D posInZoomTarget = target.parentToLocal(zoomNode.parentToLocal(mousePoint));

        Point2D adjustment = target.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));

        Bounds updatedInnerBounds = zoomNode.getBoundsInLocal();
        this.setHvalue((valX + adjustment.getX()) / (updatedInnerBounds.getWidth() - viewportBounds.getWidth()));
        this.setVvalue((valY + adjustment.getY()) / (updatedInnerBounds.getHeight() - viewportBounds.getHeight()));
    }
}
<VBox xmlns:fx="http://javafx.com/fxml/1" prefHeight="400.0" prefWidth="640.0"
      xmlns="http://javafx.com/javafx/17.0.2-ea" fx:controller="ru.itmo.grafix.ui.controllers.MainSceneController">
    <MenuBar VBox.vgrow="NEVER">
      // Some menu stuff
    </MenuBar>
    <TabPane fx:id="tabPane" tabClosingPolicy="ALL_TABS" tabDragPolicy="REORDER"/>
</VBox>

ZoomableScrollPane 实例随后锚定到 TabPane,如下所示

private ImageView setImage(WritableImage img) {
    ImageView imageView = new ImageView(img);
    ZoomableScrollPane scrP = new ZoomableScrollPane();
    scrP.setPrefSize(tabPane.getPrefWidth(), tabPane.getPrefHeight());
    getActiveTab().setContent(scrP);
    scrP.setTarget(imageView);
    return imageView;
}

private Tab getActiveTab() {
    return tabPane.getSelectionModel().getSelectedItem();
}

我遇到的问题与缩放图像的显示有关。当打开小图像并随后放大时,底部图像的一部分会被持续存在的空白区域重叠(可用屏幕截图)。 图像如下所示: broken display 而预期是这样的: Normal image display

  • 我扩展了 ScrollPane 类并实现了用于缩放的事件处理程序。
  • 图像使用 JavaFX 的 ImageView 在 ScrollPane 中显示。
  • 该问题特别出现在放大小图像时;较大的图像不会表现出这种行为。
  • 我尝试了ScrollPane的各种属性,例如fitToWidth和fitToHeight,但未能解决问题。

其他人是否遇到过类似的问题,或者可以提供有关可能导致这种重叠空白问题的见解?

java javafx scrollpane
1个回答
0
投票

Javafx 组件会根据可用的大小自动调整自身。尝试删除 prefHeight 和 prefWidth,因为它会强制组件使用特定尺寸。

© www.soinside.com 2019 - 2024. All rights reserved.