缩放形状而不将其分开

时间:2021-02-08 14:21:25

标签: javafx scale zoom-sdk

我正在尝试创建 2 个具有缩放效果的相似尺寸形状(矩形)。但是,当矩形被缩放时,这两个形状会相互重叠。此行为不符合预期。

我希望矩形被缩放(缩放),另外两个矩形应该一个在另一个下面,中间没有任何间隙。如何实现?

一种选择是在组上提供缩放。但它会使里面的文本也被缩放,这不是必需的。 另一种选择是使用 VBox,但我想在窗格上实现此功能。

有人在这里建议我一个解决方案

我试图实现的代码如下

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.input.ScrollEvent;
import javafx.stage.Stage;


@SuppressWarnings("restriction")
public class TestRectScaling extends Application {

/**
 * @param args
 */
public static void main(final String[] args) {
  launch(args);
}

/**
 * {@inheritDoc}
 */
@Override
public void start(final Stage primaryStage) throws Exception {
  javafx.scene.layout.Pane p = new javafx.scene.layout.Pane();
  javafx.scene.Group g = new javafx.scene.Group(p);
  javafx.scene.control.ScrollPane sp = new javafx.scene.control.ScrollPane(g);

  javafx.scene.layout.StackPane stackPane1 = new javafx.scene.layout.StackPane();

  javafx.scene.shape.Rectangle rect1 = new javafx.scene.shape.Rectangle();
  stackPane1.getChildren().add(rect1);
  rect1.setWidth(100);
  rect1.setHeight(100);
  rect1.setFill(javafx.scene.paint.Color.BLUE);
  javafx.scene.text.Text text1 = new javafx.scene.text.Text("This is sample Text Rect 1");
  text1.setWrappingWidth(30);
  stackPane1.getChildren().add(text1);

  javafx.scene.layout.StackPane stackPane2 = new javafx.scene.layout.StackPane();
  javafx.scene.shape.Rectangle rect2 = new javafx.scene.shape.Rectangle();
  rect2.setWidth(100);
  rect2.setHeight(100);
  rect2.setFill(javafx.scene.paint.Color.BLUEVIOLET);
  javafx.scene.text.Text text2 = new javafx.scene.text.Text("This is sample Text Rect 2");
  text2.setWrappingWidth(30);
  stackPane2.getChildren().add(rect2);
  stackPane2.getChildren().add(text2);

  stackPane1.setLayoutX(30);
  stackPane1.setLayoutY(20);

  stackPane2.setLayoutX(30);
  stackPane2.setLayoutY(120);

  g.getChildren().add(stackPane1);
  g.getChildren().add(stackPane2);


  sp.addEventFilter(javafx.scene.input.ScrollEvent.ANY, new EventHandler<ScrollEvent>() {

    @Override
    public void handle(final ScrollEvent event) {
      double scaleDelta = 1.3d;
      double scaleFactor = 0;
      double deltaY = event.getDeltaY();
      if (deltaY < 0) {
        scaleFactor = 1 / scaleDelta;
      }
      else {
        scaleFactor = scaleDelta;
      }
      rect1.setScaleY(rect1.getScaleY() * scaleFactor);
      rect2.setScaleY(rect2.getScaleY() * scaleFactor);
    }
  });

  javafx.scene.Scene s = new javafx.scene.Scene(sp);
  primaryStage.setScene(s);
  primaryStage.show();
}
}

让我帮忙拍个图

enter image description here

所以主要目的是在不改变两个矩形之间的距离的情况下缩放矩形。这基本上意味着我需要一种方法来在缩放后计算新的 Y 坐标。

2 个答案:

答案 0 :(得分:0)

不管您对实现的讨论如何,如果您仍在寻找使用当前方法的解决方案,您需要将以下侦听器包含到您的矩形 boundsInParent 属性中。

这个想法是,当你缩放一个节点时,boundsInParent 会更新。如果你听那个属性,你可以更新第二个 stackPane 的 stackPanes 和 layoutY 的高度。

double gap = 15.0;
rect1.boundsInParentProperty().addListener((obs, old, bounds) -> {
    stackPane1.setPrefHeight(bounds.getHeight());
    stackPane2.setLayoutY(stackPane1.getLayoutY() + bounds.getHeight() + gap);
});

rect2.boundsInParentProperty().addListener((obs, old, val) -> {
    stackPane2.setPrefHeight(val.getHeight());
});

更新::

以下是限制最大/最小高度缩放的演示。

import javafx.application.Application;
import javafx.stage.Stage;

public class TestRectScaling extends Application {

    double defaultHeight = 100.0;
    double maxHeight = 400.0;
    double gap = 15.0;

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

    @Override
    public void start(final Stage primaryStage) throws Exception {
        javafx.scene.layout.Pane p = new javafx.scene.layout.Pane();
        javafx.scene.Group g = new javafx.scene.Group(p);
        javafx.scene.control.ScrollPane sp = new javafx.scene.control.ScrollPane(g);

        javafx.scene.layout.StackPane stackPane1 = new javafx.scene.layout.StackPane();

        javafx.scene.shape.Rectangle rect1 = new javafx.scene.shape.Rectangle();
        stackPane1.getChildren().add(rect1);
        rect1.setWidth(100);
        rect1.setHeight(defaultHeight);
        rect1.setFill(javafx.scene.paint.Color.BLUE);
        javafx.scene.text.Text text1 = new javafx.scene.text.Text("This is sample Text Rect 1");
        text1.setWrappingWidth(30);
        stackPane1.getChildren().add(text1);

        javafx.scene.layout.StackPane stackPane2 = new javafx.scene.layout.StackPane();
        javafx.scene.shape.Rectangle rect2 = new javafx.scene.shape.Rectangle();
        rect2.setWidth(100);
        rect2.setHeight(defaultHeight);
        rect2.setFill(javafx.scene.paint.Color.BLUEVIOLET);
        javafx.scene.text.Text text2 = new javafx.scene.text.Text("This is sample Text Rect 2");
        text2.setWrappingWidth(30);
        stackPane2.getChildren().add(rect2);
        stackPane2.getChildren().add(text2);

        rect1.boundsInParentProperty().addListener((obs, old, bounds) -> {
            stackPane1.setPrefHeight(bounds.getHeight());
            stackPane2.setLayoutY(stackPane1.getLayoutY() + bounds.getHeight() + gap);
        });

        rect2.boundsInParentProperty().addListener((obs, old, val) -> {
            stackPane2.setPrefHeight(val.getHeight());
        });

        stackPane1.setLayoutX(30);
        stackPane1.setLayoutY(20);

        stackPane2.setLayoutX(30);
        stackPane2.setLayoutY(120);

        g.getChildren().add(stackPane1);
        g.getChildren().add(stackPane2);

        sp.addEventFilter(javafx.scene.input.ScrollEvent.ANY, event -> {
            double scaleDelta = 1.3d;
            double scaleFactor = 0;
            double deltaY = event.getDeltaY();
            if (deltaY < 0) {
                scaleFactor = 1 / scaleDelta;
            } else {
                scaleFactor = scaleDelta;
            }

            double scale = rect1.getScaleY() * scaleFactor;

            // Determine the resultant height of this scale.
            double scaledHeight = scale * defaultHeight;
            if(scaledHeight > maxHeight){
                // If the target height is > max, then set the scale to max height.
                scale = maxHeight/defaultHeight;
            } else if(scaledHeight < defaultHeight){
                // If the target height is < default, then set the scale to default height.
                scale = 1;
            }
            rect1.setScaleY(scale);
            rect2.setScaleY(scale);
        });

        javafx.scene.Scene s = new javafx.scene.Scene(sp);
        primaryStage.setScene(s);
        primaryStage.show();
    }
}

答案 1 :(得分:0)

通过删除下面的行,它不会真正满足比例缩放和相应地定位矩形

<块引用>

stackPane2.setLayoutY..

让我试着解释一下。

在问题中提供的程序中,进行以下更改

<块引用>

stackPane2.setLayoutX(170);

<块引用>

stackPane2.setLayoutY(100);

首先现在矩形彼此相邻。然而,有一部分矩形在 y 轴值方面具有重叠区域。 refer attached image

所以现在的问题是,一旦我们开始缩放矩形,第二个矩形的开始位置与最初放置的比例高度不同。要获得更多见解,请找到图片 representing the actual vs expected

最初,第二个矩形可能放置在第一个矩形的下 1/4 高度处。所以预期的结果是在缩放时第二个矩形应该放置在第一个矩形的 1/4 高度处。

如果我们移除了 stackPane2.setLayoutY.. 线,第二个矩形会向上移动并失去最初可用的 y 坐标。

我可以理解控件位于 stackPane2.setLayoutY.. 行中。但面临的问题是,没有正确计算 y 轴坐标。因此,第二个矩形/堆栈窗格未正确放置。

那么如何在缩放时计算第二个矩形的 y 坐标?

相关问题