【问题标题】:JAVAFX zoom, scroll in ScrollPaneJAVAFX 缩放,在 ScrollPane 中滚动
【发布时间】:2016-11-30 23:33:06
【问题描述】:

我有带有缩放和缩放功能的 JAVAFX 应用程序,如下所述: Scale at pivot point in an already scaled node 我需要实现的是将图像放置在右侧窗格中并将图像保留在左侧,如下图所示。

问题 如何将此应用程序嵌入到 SPlitPane 中,左侧将是另一个面板。

    SplitPane splitPane = new SplitPane();
    splitPane.getItems().add(new Label("Left Panel"));
    splitPane.getItems().add(group);

    Scene scene = new Scene(splitPane, 1024, 768);

不幸的是代码导致坐标错误,

【问题讨论】:

    标签: java javafx zooming scrollpane


    【解决方案1】:

    尝试添加您希望缩放和滚动到组布局的内容。然后将该组添加到滚动窗格。这将使您正在缩放的​​节点保持在滚动窗格的左侧位置。希望这能解决您的问题!

    您正在放大组内的节点, 在滚动窗格内分组, 右侧的滚动窗格 分屏!!

    【讨论】:

      【解决方案2】:

      要在ScrollPane 内进行缩放,您需要调整滚动位置。这比仅附加一个转换要复杂一些,如果没有使用ScrollPane,则可以这样做。

      基本上,您需要在缩放节点之前检查当前滚动位置,并在缩放之后修改滚动位置,以防止枢轴点因缩放因子更改而改变其位置。

      除了允许您在按住鼠标滚轮的同时移动鼠标滚轮时调整缩放之外,以下示例还允许您在网格“内”移动一个圆圈并在不单击圆圈时围绕网格移动(可平移 ScrollPane)按下 CTRL 键。

      import java.net.MalformedURLException;
      import javafx.application.Application;
      import javafx.geometry.Bounds;
      import javafx.geometry.Point2D;
      import javafx.geometry.Pos;
      import javafx.scene.Group;
      import javafx.scene.Node;
      import javafx.scene.Scene;
      import javafx.scene.canvas.Canvas;
      import javafx.scene.canvas.GraphicsContext;
      import javafx.scene.control.Label;
      import javafx.scene.control.ScrollPane;
      import javafx.scene.control.SplitPane;
      import javafx.scene.layout.Pane;
      import javafx.scene.layout.Region;
      import javafx.scene.layout.StackPane;
      import javafx.scene.paint.Color;
      import javafx.scene.shape.Circle;
      import javafx.stage.Stage;
      
      public class PivotZoom extends Application {
      
          public static Region createContent() {
              double width = 1000;
              double height = 1000;
      
              Canvas canvas = new Canvas(width, height);
              GraphicsContext gc = canvas.getGraphicsContext2D();
      
              gc.setFill(Color.LIGHTGREY);
              gc.fillRect(0, 0, width, height);
      
              gc.setStroke(Color.BLUE);
              gc.beginPath();
      
              for (int i = 50; i < width; i += 50) {
                  gc.moveTo(i, 0);
                  gc.lineTo(i, height);
              }
      
              for (int i = 50; i < height; i += 50) {
                  gc.moveTo(0, i);
                  gc.lineTo(width, i);
              }
              gc.stroke();
      
              Pane content = new Pane(
                      new Circle(50, 50, 20),
                      new Circle(120, 90, 20, Color.RED),
                      new Circle(200, 70, 20, Color.GREEN)
              );
      
              StackPane result = new StackPane(canvas, content);
              result.setAlignment(Pos.TOP_LEFT);
      
              class DragData {
      
                  double startX;
                  double startY;
                  double startLayoutX;
                  double startLayoutY;
                  Node dragTarget;
              }
      
              DragData dragData = new DragData();
      
              content.setOnMousePressed(evt -> {
                  if (evt.getTarget() != content) {
                      // initiate drag gesture, if a child of content receives the
                      // event to prevent ScrollPane from panning.
                      evt.consume();
                      evt.setDragDetect(true);
                  }
              });
      
              content.setOnDragDetected(evt -> {
                  Node n = (Node) evt.getTarget();
                  if (n != content) {
                      // set start paremeters
                      while (n.getParent() != content) {
                          n = n.getParent();
                      }
                      dragData.startX = evt.getX();
                      dragData.startY = evt.getY();
                      dragData.startLayoutX = n.getLayoutX();
                      dragData.startLayoutY = n.getLayoutY();
                      dragData.dragTarget = n;
                      n.startFullDrag();
                      evt.consume();
                  }
              });
      
              // stop dragging when mouse is released
              content.setOnMouseReleased(evt -> dragData.dragTarget = null);
      
              content.setOnMouseDragged(evt -> {
                  if (dragData.dragTarget != null) {
                      // move dragged node
                      dragData.dragTarget.setLayoutX(evt.getX() + dragData.startLayoutX - dragData.startX);
                      dragData.dragTarget.setLayoutY(evt.getY() + dragData.startLayoutY - dragData.startY);
                      Point2D p = new Point2D(evt.getX(), evt.getY());
                      evt.consume();
                  }
              });
      
              return result;
          }
      
          @Override
          public void start(Stage primaryStage) throws MalformedURLException {
              Region zoomTarget = createContent();
              zoomTarget.setPrefSize(1000, 1000);
              zoomTarget.setOnDragDetected(evt -> {
                  Node target = (Node) evt.getTarget();
                  while (target != zoomTarget && target != null) {
                      target = target.getParent();
                  }
                  if (target != null) {
                      target.startFullDrag();
                  }
              });
      
              Group group = new Group(zoomTarget);
      
              // stackpane for centering the content, in case the ScrollPane viewport
              // is larget than zoomTarget
              StackPane content = new StackPane(group);
              group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
                  // keep it at least as large as the content
                  content.setMinWidth(newBounds.getWidth());
                  content.setMinHeight(newBounds.getHeight());
              });
      
              ScrollPane scrollPane = new ScrollPane(content);
              scrollPane.setPannable(true);
              scrollPane.viewportBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
                  // use vieport size, if not too small for zoomTarget
                  content.setPrefSize(newBounds.getWidth(), newBounds.getHeight());
              });
      
              content.setOnScroll(evt -> {
                  if (evt.isControlDown()) {
                      evt.consume();
      
                      final double zoomFactor = evt.getDeltaY() > 0 ? 1.2 : 1 / 1.2;
      
                      Bounds groupBounds = group.getLayoutBounds();
                      final Bounds viewportBounds = scrollPane.getViewportBounds();
      
                      // calculate pixel offsets from [0, 1] range
                      double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth());
                      double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight());
      
                      // convert content coordinates to zoomTarget coordinates
                      Point2D posInZoomTarget = zoomTarget.parentToLocal(group.parentToLocal(new Point2D(evt.getX(), evt.getY())));
      
                      // calculate adjustment of scroll position (pixels)
                      Point2D adjustment = zoomTarget.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));
      
                      // do the resizing
                      zoomTarget.setScaleX(zoomFactor * zoomTarget.getScaleX());
                      zoomTarget.setScaleY(zoomFactor * zoomTarget.getScaleY());
      
                      // refresh ScrollPane scroll positions & content bounds
                      scrollPane.layout();
      
                      // convert back to [0, 1] range
                      // (too large/small values are automatically corrected by ScrollPane)
                      groupBounds = group.getLayoutBounds();
                      scrollPane.setHvalue((valX + adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth()));
                      scrollPane.setVvalue((valY + adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight()));
                  }
              });
      
              StackPane left = new StackPane(new Label("Left Menu"));
              SplitPane root = new SplitPane(left, scrollPane);
      
              Scene scene = new Scene(root, 800, 600);
      
              primaryStage.setScene(scene);
              primaryStage.show();
          }
      
          public static void main(String[] args) {
              launch(args);
          }
      
      }
      

      【讨论】:

      • 非常感谢。不幸的是,我需要的是拖动和缩放的组合。拖拽还是不见了
      • @RadimBurget 给你。现在可平移、可缩放并包含带有可拖动圆圈的网格...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-11
      • 2017-01-18
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2018-12-13
      相关资源
      最近更新 更多