绑定线与圆坐标不起作用

时间:2018-04-21 00:38:06

标签: javafx line

我有一个Pane,我添加2 Circle。我想将这些圆圈与一条线链接起来,并让线与圆圈一起移动(它们是可拖动的)。

draw_zone是一个窗格。

public void initialize(URL url, ResourceBundle rb) {

        vertex_list = new ArrayList<Circle>();
        edge_list = new ArrayList<Edge>();

        draw_zone.addEventHandler(MouseEvent.MOUSE_PRESSED, add_vertex_handler);

        Circle c1 = new Circle(20,50,5);
        Circle c2 = new Circle(100,120,5);
        c1.setFill(Color.RED);
        c2.setFill(Color.RED);

        edge_list.add(new Edge(c1,c2));
        Utilitaires.makeDraggable(c1);
        Utilitaires.makeDraggable(c2);
        draw_zone.getChildren().addAll(c1,c2,edge_list.get(0).line);

    }

绑定是在这个类中进行的:

public class Edge {

    public Line line;
    public Circle c1;
    public Circle c2;

    public Edge(Circle c1, Circle c2){
        this.c1 = c1;
        this.c2 = c2;
        this.line = this.connect(c1, c2);
    }



    private Line connect(Circle c1, Circle c2) {
    Line line = new Line();

    line.startXProperty().bind(c1.centerXProperty());
    line.startYProperty().bind(c1.centerYProperty());

    line.endXProperty().bind(c2.centerXProperty());
    line.endYProperty().bind(c2.centerYProperty());

    line.setStrokeWidth(1);
    //line.setStrokeLineCap(StrokeLineCap.BUTT);
    //line.getStrokeDashArray().setAll(1.0, 4.0);


    return line;
  }

我得到的结果是2 Circle与Line相关联,但当我拖动1 Circle时,Line根本不会移动。

编辑:这是makeDraggable方法

   public static void makeDraggable(Node node) {
        class T {

            double initialTranslateX, initialTranslateY,
                    anchorX, anchorY;
        }

        final T t = new T();
        if (node == null) {
            System.err.println("makeDraggable node == null");
        }
        node.setOnMousePressed(event -> {


            event.consume(); 

            t.initialTranslateX = node.getTranslateX();
            t.initialTranslateY = node.getTranslateY();


            Point2D point = node.localToParent(event.getX(), event.getY());
            t.anchorX = point.getX();
            t.anchorY = point.getY();


        });

        node.setOnMouseDragged(event -> {

            Point2D point = node.localToParent(event.getX(), event.getY());
            node.setTranslateX(t.initialTranslateX - t.anchorX + point.getX());
            node.setTranslateY(t.initialTranslateY - t.anchorY + point.getY());

        });

    } 

1 个答案:

答案 0 :(得分:1)

我会用我可怜的英语解释这里发生了什么。每个节点都有一些属性来处理节点的位置和尺寸。为了在特定位置布局节点(假设您使用的是像AnchorPane或Pane这样的布局,它们没有处理具有特定布局规则的节点),您将必须设置节点的layoutX和layoutY属性。要访问这些属性,您需要使用以下方法之一:

  • layoutXProperty() / layoutYProperty():返回属性。
  • setLayoutX(value) / setLayoutY(value):将新值设置为属性
  • relocate(xValue,yValue):调用setLayoutX和Y

现在,您可以更改节点转换,而不是设置节点位置。例如,我没有说我将节点A放到x,y = 100,50,你可以说我将节点设置为0,0但我会将x转换移动100,将y移动50.所以layoutX和layoutY将保持为0但转换属性将为X和Y的100和50.这些属性是translateX,translateY和translateZ,您可以使用以下方法访问:

  • setTranslateX(value) / setTranslateY(value)
  • translateXProperty() / translateYProperty():返回实际属性

因此,如果一切都清楚,您可以想象将对象(A)绑定到对象(B)的layoutXProperty / layoutYProperty,然后增加B对象的translateXProperty / translateYProperty将不会对A对象进行任何更改。

现在让我们谈谈Circle。在所有节点属性中,Circle还有一个是centerX和centerY。从属性的名称,您可以实际了解它们的用法。现在,与转换属性和布局属性一样,centerX和centerY也独立于其他属性。因此,如果通过更改其转换来更改节点的位置,则不会影响centerX / centerY属性的值。最后,使用构造函数Circle(double centerX, double centerY, double radius)创建一个新的Circle,实际上是设置了centerX和centerY属性,而将其他属性设置为0(layoutX,layoutY,translateX,translateY)

结论:您使用centerX和centerY绑定了Line,但是您正在更新转换属性(translateX,translateY),这就是该行保持在同一位置的原因。我建议更改makeDraggable方法,如:

    static class Delta {
        double x, y;
    }

    final Delta dragDelta = new Delta();

    private void makeDraggable(Circle circle) {
        circle.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                dragDelta.x = circle.getCenterX() - mouseEvent.getX();
                dragDelta.y = circle.getCenterY() - mouseEvent.getY();
            }
        });

        circle.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                circle.setCenterX(mouseEvent.getX() + dragDelta.x);
                circle.setCenterY(mouseEvent.getY() + dragDelta.y);
            }
        });
    }

我希望一切都清楚地表明我的观点:P

完整示例:

ShapesTest.java

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class ShapesTest extends Application {

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

    private AnchorPane root;

    @Override
    public void start(Stage stage) {

        root = new AnchorPane();

        Circle c1 = new Circle(120, 50, 20);
        Circle c2 = new Circle(300, 120, 20);
        c1.setFill(Color.RED);
        c2.setFill(Color.RED);

        makeDraggable(c1);
        makeDraggable(c2);

        Edge edj = new Edge(c1, c2);

        root.getChildren().addAll(edj.line, c1, c2);

        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.show();

    }

    static class Delta {
        double x, y;
    }

    final Delta dragDelta = new Delta();

    private void makeDraggable(Circle circle) {
        circle.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                dragDelta.x = circle.getCenterX() - mouseEvent.getX();
                dragDelta.y = circle.getCenterY() - mouseEvent.getY();
            }
        });

        circle.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                circle.setCenterX(mouseEvent.getX() + dragDelta.x);
                circle.setCenterY(mouseEvent.getY() + dragDelta.y);
            }
        });
    }
}

Edge.java和你的一样