我有一个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());
});
}
答案 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和你的一样