java - 带有视觉指示的拖放

标签 java drag-and-drop javafx line draggable

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

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

然后当我放在第二个矩形时,行尾应该绑定(bind)到它并传递一个字符串。

一方面,使用 onmouseclicked、dragged 和 release 我设法让线条跟随鼠标移动,但无法让第二个矩形知道鼠标在其上被释放(如下面的代码所示)

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();
  }
}

如果我同时使用它们,就会出问题

我该怎么做才能同时绘制线条和传递值?

最佳答案

通过在发起拖动的节点上调用 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);
    }
}

关于java - 带有视觉指示的拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25462833/

相关文章:

java - 如何阻止拖动的项目在拖放到状态栏或屏幕按钮上时消失

java - 编辑 javafx 属性上的 getValue() - 监听器未通知

javafx - 当我在列标题中双击 TableView 的分隔符时,列中的按钮消失了

java - 如何锁定 JavaFX 全屏模式?

java - XMLBeans 架构编译 - scomp 实用程序

java - 带条件提取的正则表达式

javascript - HTML5 仅拖放图像

javascript - ExtJS:寻找一个几乎像拖放一样的组件?

Java快速像素操作

java - JDBC 驱动程序连接在 NetBeans IDE 中不起作用