拖放视觉指示

时间:2014-08-23 14:13:41

标签: java drag-and-drop javafx line draggable

我正在尝试在两个对象之间实现拖放。

问题是,当我从一个矩形拖动到另一个矩形时,我需要在源矩形上连接一条线的起点,并在线的末端跟随鼠标。

然后,当我在第二个矩形处掉落时,该行的末尾应该绑定它并传递一个字符串。

一方面使用onmouseclicked,拖动和释放我设法让线跟随鼠标但是不能让第二个矩形理解鼠标已经释放(如下面的代码所示)

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;


public class Test extends Application {
double orgSceneX, orgSceneY;
double orgTranslateX, orgTranslateY;

public static void main(String[] args) {
    launch(args);
}
  @Override
  public void start(Stage primaryStage) {
    Pane root = new BorderPane();

    Rectangle rect1=new Rectangle(100,50);
    rect1.setFill(Color.AQUAMARINE);rect1.setStroke(Color.BLACK);
    Label rect1_label=new Label("Rectangle 1");
    rect1_label.setLayoutX(20);rect1_label.setLayoutY(15);
    rect1.setLayoutX(220);rect1.setLayoutY(240);

    Line line=new Line (rect1.getLayoutX()+rect1.getWidth(),rect1.getLayoutY()+rect1.getHeight()/2,
                        rect1.getLayoutX()+rect1.getWidth(),rect1.getLayoutY()+rect1.getHeight()/2);
    line.startXProperty().bind(rect1.translateXProperty().add(rect1.getLayoutX()+rect1.getWidth()));
    line.startYProperty().bind(rect1.translateYProperty().add(rect1.getLayoutY()+rect1.getHeight()/2));
    line.getStrokeDashArray().setAll(10.0, 5.0);

    Rectangle rect2=new Rectangle(100,50);
    rect2.setFill(Color.BISQUE);rect2.setStroke(Color.BLACK);
    Label rect2_label=new Label("Rectangle 2");
    rect2_label.setLayoutX(20);rect2_label.setLayoutY(15);
    rect2.setLayoutX(600);rect2.setLayoutY(240);


    root.getChildren().addAll(rect1,rect2,line);


        rect1.setOnMousePressed(new EventHandler<MouseEvent>(){
            public void handle(MouseEvent event){
                line.setVisible(true);
                line.toBack();
                line.setEndX(event.getX());
                line.setEndY(event.getY());
                orgSceneX = event.getSceneX();
                orgSceneY = event.getSceneY();
                orgTranslateX = ((Rectangle)(event.getSource())).getTranslateX();
                orgTranslateY = ((Rectangle)(event.getSource())).getTranslateY();
                line.setEndX(event.getSceneX());
                line.setEndY(event.getSceneY());
            }
        });

        rect1.setOnMouseDragged(new EventHandler<MouseEvent>(){
            public void handle(MouseEvent event)
            {
                double offsetX = event.getSceneX();
                double offsetY = event.getSceneY();
                double newTranslateX = offsetX;
                double newTranslateY = offsetY;
                line.setEndX(newTranslateX);
                line.setEndY(newTranslateY);
            }
        });

        rect1.setOnMouseReleased(new EventHandler<MouseEvent>(){
            public void handle(MouseEvent event)
            {
                line.setVisible(false);
            }
        });



    Scene scene = new Scene(root);
    primaryStage.setTitle("Nodes test 1");
    primaryStage.setMinWidth(1000);
    primaryStage.setMinHeight(600);
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

我也知道如何将值或字符串从一个对象拖放到另一个对象

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;


public class Test2 extends Application {
double orgSceneX, orgSceneY;
double orgTranslateX, orgTranslateY;

public static void main(String[] args) {
    launch(args);
}
  @Override
  public void start(Stage primaryStage) {
    Pane root = new BorderPane();

    Rectangle rect1=new Rectangle(100,50);
    rect1.setFill(Color.AQUAMARINE);rect1.setStroke(Color.BLACK);
    Label rect1_label=new Label("Rectangle 1");
    rect1_label.setLayoutX(20);rect1_label.setLayoutY(15);
    rect1.setLayoutX(220);rect1.setLayoutY(240);

    Line line=new Line (rect1.getLayoutX()+rect1.getWidth(),rect1.getLayoutY()+rect1.getHeight()/2,
                        rect1.getLayoutX()+rect1.getWidth(),rect1.getLayoutY()+rect1.getHeight()/2);
    line.startXProperty().bind(rect1.translateXProperty().add(rect1.getLayoutX()+rect1.getWidth()));
    line.startYProperty().bind(rect1.translateYProperty().add(rect1.getLayoutY()+rect1.getHeight()/2));
    line.getStrokeDashArray().setAll(10.0, 5.0);

    Rectangle rect2=new Rectangle(100,50);
    rect2.setFill(Color.BISQUE);rect2.setStroke(Color.BLACK);
    Label rect2_label=new Label("Rectangle 2");
    rect2_label.setLayoutX(20);rect2_label.setLayoutY(15);
    rect2.setLayoutX(600);rect2.setLayoutY(240);


    root.getChildren().addAll(rect1,rect2,line);

    rect1.setOnDragDetected(new EventHandler<MouseEvent>(){
        @Override public void handle(MouseEvent event){
            Dragboard db = rect1.startDragAndDrop(TransferMode.ANY);
            ClipboardContent content = new ClipboardContent();
            content.putString("rec");
            db.setContent(content);
            event.consume();
        }
    });

    rect2.setOnDragOver(new EventHandler<DragEvent>() {
        public void handle(DragEvent event) {
            event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            event.consume();
        }
    });

    rect2.setOnDragDropped(new EventHandler<DragEvent>(){
        @Override public void handle(DragEvent event){
            final Dragboard db = event.getDragboard(); 
            if (db.getString().equals("rec")){
                System.out.println("Accepted");
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            }
        }
    });

    Scene scene = new Scene(root);
    primaryStage.setTitle("Nodes test 1");
    primaryStage.setMinWidth(1000);
    primaryStage.setMinHeight(600);
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

如果我使用它们,那么一切都会出错

我可以做些什么来绘制线条以及同时传递的值?

1 个答案:

答案 0 :(得分:3)

通过在发起拖动的节点上调用startFullDrag来激活“完全按下 - 拖动释放手势”。 Javadocs for MouseEvent详细说明了拖动手势类型之间的差异,但基本上这样可以将鼠标事件传递到拖动过程中发起拖动的节点以外的节点。

但请注意,除非在该节点上按下鼠标,否则您不会在节点上获得mouseReleased事件(据我所知)。因此,您需要做一些工作来确定释放是否发生在第二个矩形上。我通过在拖动过程中鼠标进入节点时设置标志并在退出时将其设置为false来完成此操作。您也可以通过在底层容器上查找鼠标释放,并查看节点的边界是否包含鼠标事件的坐标来执行此操作。

另请注意,在此示例中,我需要调用line.setMouseTransparent(true);以确保该行没有消耗鼠标事件。

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class DragAndDropWithLine extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Rectangle rect1 = new Rectangle(50, 50, 50, 100);
        rect1.setFill(Color.YELLOW);

        Rectangle rect2 = new Rectangle(200, 50, 50, 100);
        rect2.setFill(Color.BLUE);

        Line line = new Line();
        line.setMouseTransparent(true);

        pane.getChildren().addAll(rect1, rect2);

        BooleanProperty dragging = new SimpleBooleanProperty();
        BooleanProperty draggingOverRect2 = new SimpleBooleanProperty();

        rect1.setOnDragDetected(event -> {
            rect1.startFullDrag();
            Point2D mouseSceneCoords = new Point2D(event.getSceneX(), event.getSceneY());
            Point2D mousePaneCoords = pane.sceneToLocal(mouseSceneCoords);
            line.setStartX(mousePaneCoords.getX());
            line.setStartY(mousePaneCoords.getY());
            line.setEndX(mousePaneCoords.getX());
            line.setEndY(mousePaneCoords.getY());
            pane.getChildren().add(line);
            dragging.set(true);
        });

        pane.setOnMouseDragged(event -> {
            if (dragging.get()) {
                line.setEndX(event.getX());
                line.setEndY(event.getY());
            }
        });

        rect1.setOnMouseReleased(event -> {
            if (draggingOverRect2.get()) {
                pane.getChildren().remove(rect1);
                rect2.setFill(Color.GREEN);
            }
            dragging.set(false);
            draggingOverRect2.set(false);
            pane.getChildren().remove(line);
        });

        rect2.setOnMouseDragEntered(event -> {
            if (dragging.get()) {
                draggingOverRect2.set(true);
            }
        });

        rect2.setOnMouseDragExited(event -> draggingOverRect2.set(false));


        primaryStage.setScene(new Scene(pane, 300, 200));
        primaryStage.show();
    }

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