当前位置: 首页 > 知识库问答 >
问题:

JavaFX-ImageView和Pane的边框不能在ScrollPane中正确缩放/缩放

段干跃
2023-03-14

为了实现类似于minimap的功能,我使用StackPaneImageView之上添加了一个窗格。我将StackPane的缩放x和y属性绑定到滑块以实现缩放效果。我在窗格中添加了一些循环对象。这些圆圈当然也应该是可缩放的(它们确实是),但在这种情况下,更重要的是,当缩放发生时,它们应该保持在它们的相对位置。下面的图片显示了GUI到目前为止的样子。

到目前为止,我已经区分了两个有问题的案例。

在这个更简单的例子中,除了放大图像似乎使其超出StackPane的边界之外,一切都很好。因此,您不能再滚动到图像的边框。查看下一张截图,看看我的意思。

为了使StackPane适当增长,我将其大小属性绑定到缩放系数乘以图像大小。然而,我很确定这种方法在某种程度上扰乱了底层的坐标结构,因为现在圆“离开”它的位置在一个大于1的比例因子。上述行为描述在最后一张截图中。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class ScalingProblem extends Application {

    private static final String IMAGE_URL = "https://st2.depositphotos.com/3034795/10774/i/950/depositphotos_107745620-stock-photo-labyrinth-or-maze.jpg";

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

        // Prepare the main part of the GUI.
        Image backgroundImage = new Image(IMAGE_URL);
        ImageView imageView = new ImageView(backgroundImage);
        Circle circle = new Circle(40, Color.ORANGE);
        circle.setStroke(Color.BLUE);
        circle.setStrokeWidth(5);
        Pane layer = new Pane(circle);
        StackPane stackPane = new StackPane(imageView, layer);
        ScrollPane scrollPane = new ScrollPane(stackPane);
        scrollPane.setPannable(true);

        // Prepare the controls on the left side.
        Slider xSlider = new Slider();
        Slider ySlider = new Slider();
        Slider radiusSlider = new Slider();
        Slider zoomSlider = new Slider();
        VBox vBox = new VBox(xSlider, ySlider, radiusSlider, zoomSlider);
        vBox.setSpacing(10);
        vBox.setPrefWidth(200);

        // Adjust the sliders.
        adjustSlider(xSlider, 0, 1000, 50);
        adjustSlider(ySlider, 0, 1000, 50);
        adjustSlider(radiusSlider, 0, 100, 15);
        adjustSlider(zoomSlider, 0, 3, 1);
        zoomSlider.setMajorTickUnit(1);
        zoomSlider.setMinorTickCount(1);
        zoomSlider.setShowTickMarks(true);
        zoomSlider.setShowTickLabels(true);

        // Do all necessary binding.
        circle.centerXProperty().bind(xSlider.valueProperty());
        circle.centerYProperty().bind(ySlider.valueProperty());
        circle.radiusProperty().bind(radiusSlider.valueProperty());
        stackPane.scaleXProperty().bind(zoomSlider.valueProperty());
        stackPane.scaleYProperty().bind(zoomSlider.valueProperty());
        /*
         * So far, I always needed to make the StackPane's size grow / shrink depending on the zoom level. If the
         * following two lines are commented out, zooming in will make the ImageView exceed the bounds of the StackPane.
         * As a result, the StackPane does not 'grow' appropriately so that you cannot pan the view to see the edges of
         * the background.
         */
        stackPane.prefWidthProperty().bind(zoomSlider.valueProperty().multiply(backgroundImage.getWidth()));
        stackPane.prefHeightProperty().bind(zoomSlider.valueProperty().multiply(backgroundImage.getHeight()));

        // Piece the GUI together.
        BorderPane root = new BorderPane();
        root.setCenter(scrollPane);
        root.setLeft(vBox);
        root.setPrefHeight(300);
        root.setPrefWidth(500);

        // Show the stage.
        primaryStage.setScene(new Scene(root));
        primaryStage.show();

    }

    private void adjustSlider(Slider slider, double min, double max, double start) {
        slider.setMin(min);
        slider.setMax(max);
        slider.setValue(start);
    }

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

共有1个答案

郭麒
2023-03-14

ScrollPane使用未修改的布局边界来确定内容大小。这不包括缩放转换。若要防止内容超出可滚动区域,请将缩放的节点包装在中。

按以下方式修改ScrollPane创建:

ScrollPane scrollPane = new ScrollPane(new Group(stackPane));

并移除对prefwidth/prefheight的绑定,即删除以下行:

stackPane.prefWidthProperty().bind(zoomSlider.valueProperty().multiply(backgroundImage.getWidth()));
stackPane.prefHeightProperty().bind(zoomSlider.valueProperty().multiply(backgroundImage.getHeight()));
 类似资料:
  • 问题内容: 我需要在滚动窗格上相对于鼠标位置放大/缩小。 我目前通过将内容包装在一个组中并缩放组本身来实现缩放功能。我用自定义枢轴创建一个新的Scale对象。(枢轴设置为鼠标位置) 这在Group的初始比例为1.0的情况下非常适用,但是之后的缩放比例无法沿正确的方向缩放-我相信这是因为Group缩放后相对鼠标位置会发生变化。 我的代码: 如何在不同的缩放级别上获得正确的鼠标位置?有没有一种更简单的

  • 我一直在尝试使用JavaFX中的缩放转换,但还没有完全理解它。基本上,我有一个窗格包含一个复杂的图形,并希望能够撤销它。缩放部分本身工作得很好,但是,封闭的滚动窗格将不适应图形。 为了简单起见,我将发布一个简短的示例,其中我的图被一个标签替换: null 我错过了什么?如何使滚动窗格适应内容视图? 谢谢你的帮助。

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

  • 我试图放大我的mandelbrot集,我读到了这个问题:如何简单地放大mandelbrot集,但我很难理解它,它不起作用。当我这样计算新的实数和复数时: 新的mandelbrot在两个轴上都有点变形?怎么了?以下是一个例子:http://www.phpdevpad.de/index.php?id=190.

  • 问题内容: 是否有仅css的解决方案将图像缩放到边框(保持纵横比)?如果图像大于容器,则此方法有效: 问题答案: 不,没有唯一的CSS双向方式可以做到这一点。您可以添加 对于一个元素,使其始终具有100%的宽度,并自动将其高度缩放为长宽比, 或 反之: 始终缩放到最大高度和相对宽度。为此,您需要确定纵横比是高于还是低于容器,而CSS无法做到这一点。 原因是CSS不知道页面的外观。它会预先设置规则,

  • 实际上,我正在用JavaFX编写游戏《暗黑破坏神》的“简单”版本。 目前,屏幕尺寸为绝对800x600,一切正常。现在我们的团队希望在每个桌面上使用全屏。 我的问题是:我们正在使用绝对尺寸为25x25的墙、地板等图像。如果我们想在全屏模式下工作,我们需要扩展它们。 但据我所知,您只能缩放ImageView或BufferedImage。当然,我们正在重复使用图像。例如,一个墙壁纹理在窗格上出现了20