2016-10-26 5 views
1

Ich habe 2 Knoten, 1 Kreis und 1 Rechteck. Beide sind Drag-and-Dropable.JavaFX 2 Knoten gleichzeitig ziehen

Gibt es eine Möglichkeit, sie zu kombinieren, so dass ich eine von ihnen ziehen und ablegen kann und beide bewegt werden? Ich habe bereits versucht, eine Gruppe zu erstellen und beide Knoten als Kinder hinzufügen (das hat nicht für mich funktioniert). Hier ist ein Beispielcode, der interessante Teil ist die Klasse ZoomAndScrollApplication am unteren Rand. Es schafft einen Kreis und ein Rechteck (und 3 Etiketten) alle von ihnen sind ziehbar, aber ich möchte das Rechteck und den Kreis verbinden (das ich sie beide nur durch Anklicken einer von ihnen ziehen):

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.Node; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.control.Label; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Circle; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 

class PannableCanvas extends Pane { 

    DoubleProperty myScale = new SimpleDoubleProperty(1.0); 

    public PannableCanvas() { 
     setPrefSize(600, 600); 
     setStyle("-fx-background-color: lightgrey; -fx-border-color: blue;"); 

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

    /** 
    * Add a grid to the canvas, send it to back 
    */ 
    public void addGrid() { 

     double w = getBoundsInLocal().getWidth(); 
     double h = getBoundsInLocal().getHeight(); 

     // add grid 
     Canvas grid = new Canvas(w, h); 

     // don't catch mouse events 
     grid.setMouseTransparent(true); 

     GraphicsContext gc = grid.getGraphicsContext2D(); 

     gc.setStroke(Color.GRAY); 
     gc.setLineWidth(1); 

     // draw grid lines 
     double offset = 50; 
     for(double i=offset; i < w; i+=offset) { 
      gc.strokeLine(i, 0, i, h); 
      gc.strokeLine(0, i, w, i); 
     } 

     getChildren().add(grid); 

     grid.toBack(); 
    } 

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

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

    public void setPivot(double x, double y) { 
     setTranslateX(getTranslateX()-x); 
     setTranslateY(getTranslateY()-y); 
    } 
} 


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

    double mouseAnchorX; 
    double mouseAnchorY; 

    double translateAnchorX; 
    double translateAnchorY; 

} 

/** 
* Listeners for making the nodes draggable via left mouse button. Considers if parent is zoomed. 
*/ 
class NodeGestures { 

    private DragContext nodeDragContext = new DragContext(); 

    PannableCanvas canvas; 

    public NodeGestures(PannableCanvas canvas) { 
     this.canvas = canvas; 

    } 

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

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

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

     public void handle(MouseEvent event) { 

      // left mouse button => dragging 
      if(!event.isPrimaryButtonDown()) 
       return; 

      nodeDragContext.mouseAnchorX = event.getSceneX(); 
      nodeDragContext.mouseAnchorY = event.getSceneY(); 

      Node node = (Node) event.getSource(); 

      nodeDragContext.translateAnchorX = node.getTranslateX(); 
      nodeDragContext.translateAnchorY = node.getTranslateY(); 

     } 

    }; 

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

      // left mouse button => dragging 
      if(!event.isPrimaryButtonDown()) 
       return; 

      double scale = canvas.getScale(); 

      Node node = (Node) event.getSource(); 

      node.setTranslateX(nodeDragContext.translateAnchorX + ((event.getSceneX() - nodeDragContext.mouseAnchorX)/scale)); 
      node.setTranslateY(nodeDragContext.translateAnchorY + ((event.getSceneY() - nodeDragContext.mouseAnchorY)/scale)); 

      event.consume(); 

     } 
    }; 
} 

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

    private static final double MAX_SCALE = 10.0d; 
    private static final double MIN_SCALE = .1d; 

    private DragContext sceneDragContext = new DragContext(); 

    PannableCanvas canvas; 

    public SceneGestures(PannableCanvas canvas) { 
     this.canvas = canvas; 
    } 

    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) { 

      // right mouse button => panning 
      if(!event.isSecondaryButtonDown()) 
       return; 

      sceneDragContext.mouseAnchorX = event.getSceneX(); 
      sceneDragContext.mouseAnchorY = event.getSceneY(); 

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

     } 

    }; 

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

      // right mouse button => panning 
      if(!event.isSecondaryButtonDown()) 
       return; 

      canvas.setTranslateX(sceneDragContext.translateAnchorX + event.getSceneX() - sceneDragContext.mouseAnchorX); 
      canvas.setTranslateY(sceneDragContext.translateAnchorY + event.getSceneY() - 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 = 1.2; 

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

      if (event.getDeltaY() < 0) 
       scale /= delta; 
      else 
       scale *= delta; 

      scale = clamp(scale, MIN_SCALE, MAX_SCALE); 

      double f = (scale/oldScale)-1; 

      double dx = (event.getSceneX() - (canvas.getBoundsInParent().getWidth()/2 + canvas.getBoundsInParent().getMinX())); 
      double dy = (event.getSceneY() - (canvas.getBoundsInParent().getHeight()/2 + canvas.getBoundsInParent().getMinY())); 

      canvas.setScale(scale); 

      // note: pivot value must be untransformed, i. e. without scaling 
      canvas.setPivot(f*dx, f*dy); 

      event.consume(); 

     } 

    }; 


    public static double clamp(double value, double min, double max) { 

     if(Double.compare(value, min) < 0) 
      return min; 

     if(Double.compare(value, max) > 0) 
      return max; 

     return value; 
    } 
} 



/** 
* An application with a zoomable and pannable canvas. 
*/ 
public class ZoomAndScrollApplication extends Application { 
    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 

     Group group = new Group(); 

     // create canvas 
     PannableCanvas canvas = new PannableCanvas(); 

     // we don't want the canvas on the top/left in this example => just 
     // translate it a bit 
     canvas.setTranslateX(100); 
     canvas.setTranslateY(100); 

     // create sample nodes which can be dragged 
     NodeGestures nodeGestures = new NodeGestures(canvas); 

     Label label1 = new Label("Draggable node 1"); 
     label1.setTranslateX(10); 
     label1.setTranslateY(10); 
     label1.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
     label1.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

     Label label2 = new Label("Draggable node 2"); 
     label2.setTranslateX(100); 
     label2.setTranslateY(100); 
     label2.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
     label2.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

     Label label3 = new Label("Draggable node 3"); 
     label3.setTranslateX(200); 
     label3.setTranslateY(200); 
     label3.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
     label3.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

     Circle circle1 = new Circle(300, 300, 50); 
     circle1.setStroke(Color.ORANGE); 
     circle1.setFill(Color.ORANGE.deriveColor(1, 1, 1, 0.5)); 
     circle1.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
     circle1.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

     Rectangle rect1 = new Rectangle(100,100); 
     rect1.setTranslateX(450); 
     rect1.setTranslateY(450); 
     rect1.setStroke(Color.BLUE); 
     rect1.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.5)); 
     rect1.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
     rect1.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

     canvas.getChildren().addAll(label1, label2, label3, circle1, rect1); 

     group.getChildren().add(canvas); 

     // create scene which can be dragged and zoomed 
     Scene scene = new Scene(group, 1024, 768); 

     SceneGestures sceneGestures = new SceneGestures(canvas); 
     scene.addEventFilter(MouseEvent.MOUSE_PRESSED, sceneGestures.getOnMousePressedEventHandler()); 
     scene.addEventFilter(MouseEvent.MOUSE_DRAGGED, sceneGestures.getOnMouseDraggedEventHandler()); 
     scene.addEventFilter(ScrollEvent.ANY, sceneGestures.getOnScrollEventHandler()); 

     stage.setScene(scene); 
     stage.show(); 

     canvas.addGrid(); 

    } 
} 
+0

Mit einem 'Group' sollte funktionieren, richtig gemacht. Schließen Sie Ihren Versuch mit der 'Gruppe' in der Frage ein und beschreiben Sie, wie dieser Ansatz fehlschlägt. – fabian

+0

Sagen Sie uns die Logik.Sie wollen, wenn der Benutzer den 'Circle' oder' Rectangle' ziehen die beide entfernt und zu anderen Container hinzugefügt werden? – GOXR3PLUS

+0

ok warten Sie im Erstellen eines Beispielprojekts – stronglion3001

Antwort

1

Sie sagte uns mit einer Group funktioniert nicht. Das ist einfach nicht wahr, und nur eine kleine in Codeänderung erforderlich Circle und Rectangle zugleich zu bewegen, ein Group: if

Circle circle1 = new Circle(300, 300, 50); 
circle1.setStroke(Color.ORANGE); 
circle1.setFill(Color.ORANGE.deriveColor(1, 1, 1, 0.5)); 
// circle1.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
// circle1.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

Rectangle rect1 = new Rectangle(100, 100); 
rect1.setTranslateX(450); 
rect1.setTranslateY(450); 
rect1.setStroke(Color.BLUE); 
rect1.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.5)); 
// rect1.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
// rect1.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

Group g = new Group(rect1, circle1); 
g.addEventFilter(MouseEvent.MOUSE_PRESSED, nodeGestures.getOnMousePressedEventHandler()); 
g.addEventFilter(MouseEvent.MOUSE_DRAGGED, nodeGestures.getOnMouseDraggedEventHandler()); 

canvas.getChildren().addAll(label1, label2, label3, g); 
+0

und Sie sind richtig. Ich war dieser Doumb und habe die Gruppe nicht auf die Leinwand "Kinder!" Danke – stronglion3001