2015-04-22 16 views
5

मैं ScrollPane के साथ एक दृश्य को कार्यान्वित करने की कोशिश कर रहा हूं जिसमें उपयोगकर्ता नोड को खींच सकता है और इसे गतिशील रूप से स्केल कर सकता है। मेरे पास माउस व्हील के साथ-साथ रीसेट ज़ूम के साथ ड्रैगिंग और स्केलिंग है, लेकिन मुझे नोड को पैरेंट की चौड़ाई तक फिट करने के लिए गणनाओं में परेशानी हो रही है।जावाएफएक्स 8 डायनामिक नोड स्केलिंग

मेरा कोड sscce के रूप में है।

  1. (काम करता है) माउस व्हील आयत खींचें करने के लिए माउस सूचक
  2. (काम) बाएं या दाएं माउस प्रेस चारों ओर अंदर और बाहर ज़ूम जाएगा चारों ओर
  3. (काम) डबल क्लिक करें ज़ूम रीसेट करने के लिए वाम
  4. (काम नहीं करता है) सही अगर मैं में ज़ूम या बाहर या विंडो का आकार बदलने चौड़ाई

फिट करने के लिए डबल क्लिक करें, चौड़ाई के लिए फिट काम नहीं करता।

यदि कोई मुझे माता-पिता की चौड़ाई तक नोड फिट करने की गणना के साथ मेरी मदद कर सकता है, तो मैं इसकी बहुत सराहना करता हूं।

संपादित:

  • मैं विधि है कि सही ढंग से काम नहीं कर रहा है चिह्नित। यह fitWidth() है, जिसे दायां माउस बटन डबल-क्लिक करके बुलाया जाता है।
  • मैं स्पष्टता के लिए प्रश्न के पाठ संपादित और ध्यान केंद्रित

उम्मीद है कि यह अब और अधिक स्पष्ट है।

import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.ScrollPane.ScrollBarPolicy; 
import javafx.scene.input.MouseButton; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.scene.shape.StrokeType; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class ZoomAndPanExample extends Application { 

    private ScrollPane scrollPane = new ScrollPane(); 

    private final DoubleProperty zoomProperty = new SimpleDoubleProperty(1.0d); 
    private final DoubleProperty deltaY = new SimpleDoubleProperty(0.0d); 

    private final Group group = new Group(); 

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

    @Override 
    public void start(Stage primaryStage) { 

     scrollPane.setPannable(true); 
     scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER); 
     scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER); 
     AnchorPane.setTopAnchor(scrollPane, 10.0d); 
     AnchorPane.setRightAnchor(scrollPane, 10.0d); 
     AnchorPane.setBottomAnchor(scrollPane, 10.0d); 
     AnchorPane.setLeftAnchor(scrollPane, 10.0d); 

     AnchorPane root = new AnchorPane(); 

     Rectangle rect = new Rectangle(80, 60); 

     rect.setStroke(Color.NAVY); 
     rect.setFill(Color.NAVY); 
     rect.setStrokeType(StrokeType.INSIDE); 

     group.getChildren().add(rect); 
     // create canvas 
     PanAndZoomPane panAndZoomPane = new PanAndZoomPane(); 
     zoomProperty.bind(panAndZoomPane.myScale); 
     deltaY.bind(panAndZoomPane.deltaY); 
     panAndZoomPane.getChildren().add(group); 

     SceneGestures sceneGestures = new SceneGestures(panAndZoomPane); 

     scrollPane.setContent(panAndZoomPane); 
     panAndZoomPane.toBack(); 
     scrollPane.addEventFilter(MouseEvent.MOUSE_CLICKED, sceneGestures.getOnMouseClickedEventHandler()); 
     scrollPane.addEventFilter(MouseEvent.MOUSE_PRESSED, sceneGestures.getOnMousePressedEventHandler()); 
     scrollPane.addEventFilter(MouseEvent.MOUSE_DRAGGED, sceneGestures.getOnMouseDraggedEventHandler()); 
     scrollPane.addEventFilter(ScrollEvent.ANY, sceneGestures.getOnScrollEventHandler()); 

     root.getChildren().add(scrollPane); 
     Scene scene = new Scene(root, 600, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    class PanAndZoomPane extends Pane { 

     public static final double DEFAULT_DELTA = 1.3d; 
     DoubleProperty myScale = new SimpleDoubleProperty(1.0); 
     public DoubleProperty deltaY = new SimpleDoubleProperty(0.0); 
     private Timeline timeline; 


     public PanAndZoomPane() { 

      this.timeline = new Timeline(60); 

      // add scale transform 
      scaleXProperty().bind(myScale); 
      scaleYProperty().bind(myScale); 
     } 


     public double getScale() { 
      return myScale.get(); 
     } 

     public void setScale(double scale) { 
      myScale.set(scale); 
     } 

     public void setPivot(double x, double y, double scale) { 
      // note: pivot value must be untransformed, i. e. without scaling 
      // timeline that scales and moves the node 
      timeline.getKeyFrames().clear(); 
      timeline.getKeyFrames().addAll(
       new KeyFrame(Duration.millis(200), new KeyValue(translateXProperty(), getTranslateX() - x)), 
       new KeyFrame(Duration.millis(200), new KeyValue(translateYProperty(), getTranslateY() - y)), 
       new KeyFrame(Duration.millis(200), new KeyValue(myScale, scale)) 
      ); 
      timeline.play(); 

     } 

    /** 
    * !!!! The problem is in this method !!!! 
    * 
    * The calculations are incorrect, and result in unpredictable behavior 
    * 
    */ 
     public void fitWidth() { 
      double scale = getParent().getLayoutBounds().getMaxX()/getLayoutBounds().getMaxX(); 
      double oldScale = getScale(); 

      double f = (scale/oldScale)-1; 

      double dx = getTranslateX() - getBoundsInParent().getMinX() - getBoundsInParent().getWidth()/2; 
      double dy = getTranslateY() - getBoundsInParent().getMinY() - getBoundsInParent().getHeight()/2; 

      double newX = f*dx + getBoundsInParent().getMinX(); 
      double newY = f*dy + getBoundsInParent().getMinY(); 

      setPivot(newX, newY, scale); 

     } 

     public void resetZoom() { 
      double scale = 1.0d; 

      double x = getTranslateX(); 
      double y = getTranslateY(); 

      setPivot(x, y, scale); 
     } 

     public double getDeltaY() { 
      return deltaY.get(); 
     } 
     public void setDeltaY(double dY) { 
      deltaY.set(dY); 
     } 
    } 


    /** 
    * Mouse drag context used for scene and nodes. 
    */ 
    class DragContext { 

     double mouseAnchorX; 
     double mouseAnchorY; 

     double translateAnchorX; 
     double translateAnchorY; 

    } 

    /** 
    * Listeners for making the scene's canvas draggable and zoomable 
    */ 
    public class SceneGestures { 

     private DragContext sceneDragContext = new DragContext(); 

     PanAndZoomPane panAndZoomPane; 

     public SceneGestures(PanAndZoomPane canvas) { 
      this.panAndZoomPane = canvas; 
     } 

     public EventHandler<MouseEvent> getOnMouseClickedEventHandler() { 
      return onMouseClickedEventHandler; 
     } 

     public EventHandler<MouseEvent> getOnMousePressedEventHandler() { 
      return onMousePressedEventHandler; 
     } 

     public EventHandler<MouseEvent> getOnMouseDraggedEventHandler() { 
      return onMouseDraggedEventHandler; 
     } 

     public EventHandler<ScrollEvent> getOnScrollEventHandler() { 
      return onScrollEventHandler; 
     } 

     private EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() { 

      public void handle(MouseEvent event) { 

       sceneDragContext.mouseAnchorX = event.getX(); 
       sceneDragContext.mouseAnchorY = event.getY(); 

       sceneDragContext.translateAnchorX = panAndZoomPane.getTranslateX(); 
       sceneDragContext.translateAnchorY = panAndZoomPane.getTranslateY(); 

      } 

     }; 

     private EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() { 
      public void handle(MouseEvent event) { 

       panAndZoomPane.setTranslateX(sceneDragContext.translateAnchorX + event.getX() - sceneDragContext.mouseAnchorX); 
       panAndZoomPane.setTranslateY(sceneDragContext.translateAnchorY + event.getY() - sceneDragContext.mouseAnchorY); 

       event.consume(); 
      } 
     }; 

     /** 
     * Mouse wheel handler: zoom to pivot point 
     */ 
     private EventHandler<ScrollEvent> onScrollEventHandler = new EventHandler<ScrollEvent>() { 

      @Override 
      public void handle(ScrollEvent event) { 

       double delta = PanAndZoomPane.DEFAULT_DELTA; 

       double scale = panAndZoomPane.getScale(); // currently we only use Y, same value is used for X 
       double oldScale = scale; 

       panAndZoomPane.setDeltaY(event.getDeltaY()); 
       if (panAndZoomPane.deltaY.get() < 0) { 
        scale /= delta; 
       } else { 
        scale *= delta; 
       } 

       double f = (scale/oldScale)-1; 

       double dx = (event.getX() - (panAndZoomPane.getBoundsInParent().getWidth()/2 + panAndZoomPane.getBoundsInParent().getMinX())); 
       double dy = (event.getY() - (panAndZoomPane.getBoundsInParent().getHeight()/2 + panAndZoomPane.getBoundsInParent().getMinY())); 

       panAndZoomPane.setPivot(f*dx, f*dy, scale); 

       event.consume(); 

      } 
     }; 

     /** 
     * Mouse click handler 
     */ 
     private EventHandler<MouseEvent> onMouseClickedEventHandler = new EventHandler<MouseEvent>() { 

      @Override 
      public void handle(MouseEvent event) { 
       if (event.getButton().equals(MouseButton.PRIMARY)) { 
        if (event.getClickCount() == 2) { 
         panAndZoomPane.resetZoom(); 
        } 
       } 
       if (event.getButton().equals(MouseButton.SECONDARY)) { 
        if (event.getClickCount() == 2) { 
         panAndZoomPane.fitWidth(); 
        } 
       } 
      } 
     }; 
    } 
} 
+0

यह शायद [कोड समीक्षा] (http://codereview.stackexchange.com) के लिए एक बेहतर विकल्प है। – royhowie

+0

@royhowie नहीं, अगर यह कोड समीक्षा पर पोस्ट किया गया है तो यह बंद हो जाएगा क्योंकि यह ठीक से काम नहीं कर रहा है। – Hosch250

+0

@ होश 250 आपका प्रश्न यह ध्वनि बनाता है जैसे कि सबकुछ काम करता है (मोटे तौर पर) और कुछ पहलुओं को केवल परिशोधन की आवश्यकता होती है – royhowie

उत्तर

0

मुझे जवाब मिला। मैं गलत गणनाओं को देख रहा था, यह मानते हुए कि यह अनुवाद से संबंधित है। असली अपराधी पैमाने में अंतर के लिए गणना थी।

double f = (scale/oldScale)-1;

इस के लिए

: मैं बस यह बदल

double f = scale - oldScale;

संबंधित मुद्दे