2016-07-27 138 views
4

我有變焦和規模的JavaFX應用程序如下所述: Scale at pivot point in an already scaled node 我需要實現的是將圖像放置到右側窗格中,保持圖像的左邊,如下圖所示。 enter image description hereJavaFX的縮放,滾動的ScrollPane

問題 如何能夠將這種應用到SPlitPane,其中左邊將是另一個面板。

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

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

不幸的是,代碼導致錯誤的座標,

回答

1

嘗試增加什麼是你希望放大和滾動到一個組佈局。然後將該組添加到滾動窗格。這將保持您正在放大滾動窗格左側位置的節點。希望這能解決你的問題!

節點你在室內組變焦, 集團內的滾動面板, 滾動面板上 Splitpane的rightside!

3

要放大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); 
    } 

} 
+0

非常感謝。不幸的是我需要的是拖動和縮放的組合。拖動仍然丟失 –

+0

@RadimBurget在這裏,你去。 Pannable,可縮放幷包含可拖動圓圈的網格... – fabian