在下面的JavaFX代码中,输出两个顶点(圆圈),其中有一条从源到目标的有向边(线和箭头)。但是,箭头始终是圆的中心。我希望箭头在拖动时始终指向圆的边缘。
主类(TestArrow.java):
import java.util.ArrayList;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class TestArrow extends Application
{
int startX = 20,
startY = 20,
endX = 200,
endY = 200;
ArrayList<ArrowSecond> arrows = new ArrayList<>();
@Override
public void start(Stage primaryStage)
{
AnchorPane root = new AnchorPane();
Line line = new Line(startX, startY, endX, endY);
line.setStrokeWidth(3);
line.setStroke(Color.BLACK);
AnchorSecond start = new AnchorSecond(Color.BLACK, line.startXProperty(), line.startYProperty(), this);
AnchorSecond end = new AnchorSecond(Color.BLACK, line.endXProperty(), line.endYProperty(), this);
double[] points = {0.0, 10.0, -10.0, -10.0, 10.0, -10.0};
arrows.add(new ArrowSecond(points, line));
root.getChildren().addAll(arrows);
root.getChildren().addAll(line, start, end);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public ArrayList<ArrowSecond> getArrows(){
return arrows;
}
public static void main(String[] args){
launch(args);
}
}
箭头类(ArrowSecond.java):
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
public class ArrowSecond extends Polygon
{
private Line line;
public ArrowSecond(double[] points, Line line)
{
super(points);
this.line = line;
initialize();
}
private void initialize()
{
double angle = Math.atan2(line.getEndY() - line.getStartY(), line.getEndX() - line.getStartX()) * 180 / 3.14;
setRotate(angle - 90);
setTranslateX(line.getStartX());
setTranslateY(line.getStartY());
setTranslateX(line.getEndX());
setTranslateY(line.getEndY());
}
public void update(){
initialize();
}
}
顶点类(AnchorSecond.java):
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.StrokeType;
public class AnchorSecond extends Circle
{
private double x, y;
TestArrow app;
public AnchorSecond(Color color, DoubleProperty xx, DoubleProperty yy, TestArrow app)
{
// x point y point radius
super(xx.get(), yy.get(), 12);
this.app = app;
setFill(color.deriveColor(1, 1, 1, 0.5));
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
xx.bind(centerXProperty());
yy.bind(centerYProperty());
setOnMousePressed(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent mouseEvent)
{
x = getCenterX() - mouseEvent.getX();
y = getCenterY() - mouseEvent.getY();
}
});
setOnMouseDragged(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event)
{
setCenterX(event.getSceneX() - x);
setCenterY(event.getSceneY() - y);
// update arrow positions when circles are dragged
for(ArrowSecond arrow : app.getArrows())
arrow.update();
}
});
}
}
答案 0 :(得分:2)
这是我的解决方案:
我从结束X中减去并根据节点的半径结束Y坐标。数学很简单 - 我只是从斜边减去比例。
TestArrow类:
public class TestArrow extends Application {
int startX = 20, startY = 20, endX = 200, endY = 200;
ArrayList<ArrowSecond> arrows = new ArrayList<>();
@Override
public void start(Stage primaryStage)
{
double radius = 12;
AnchorPane root = new AnchorPane();
Line line = new Line(startX, startY, endX, endY);
line.setStrokeWidth(3);
line.setStroke(Color.BLACK);
AnchorSecond start = new AnchorSecond(Color.BLACK, line.startXProperty(), line.startYProperty(), radius, this);
AnchorSecond end = new AnchorSecond(Color.BLACK, line.endXProperty(), line.endYProperty(), radius, this);
double[] points = {0.0, 10.0, -10.0, -10.0, 10.0, -10.0};
arrows.add(new ArrowSecond(points, line, radius));
root.getChildren().addAll(arrows);
root.getChildren().addAll(start, end, line);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
public ArrayList<ArrowSecond> getArrows(){
return arrows;
}
public static void main(String[] args){
launch(args);
}
}
ArrowSecond类:
public class ArrowSecond extends Polygon {
private Line line;
double radius;
public ArrowSecond(double[] points, Line line, double AnchorRadius) {
super(points);
this.line = line;
this.radius = AnchorRadius * 2;
initialize();
}
private void initialize() {
double angle = Math.atan2(line.getEndY() - line.getStartY(), line.getEndX() - line.getStartX()) * 180 / 3.14;
double height = line.getEndY() - line.getStartY();
double width = line.getEndX() - line.getStartX();
double length = Math.sqrt(Math.pow(height, 2) + Math.pow(width, 2));
double subtractWidth = radius * width / length;
double subtractHeight = radius * height / length;
setRotate(angle - 90);
setTranslateX(line.getStartX());
setTranslateY(line.getStartY());
setTranslateX(line.getEndX() - subtractWidth);
setTranslateY(line.getEndY() - subtractHeight);
}
public void update(){
initialize();
}
}
AnchorSecond类:
public class AnchorSecond extends Circle {
private double x, y;
TestArrow app;
public AnchorSecond(Color color, DoubleProperty xx, DoubleProperty yy, double radius, TestArrow app) {
// x point y point radius
super(xx.get(), yy.get(), radius);
this.app = app;
setFill(color.deriveColor(1, 1, 1, 0.5));
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
xx.bind(centerXProperty());
yy.bind(centerYProperty());
setOnMousePressed(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent mouseEvent)
{
x = getCenterX() - mouseEvent.getX();
y = getCenterY() - mouseEvent.getY();
}
});
setOnMouseDragged(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event)
{
setCenterX(event.getSceneX() - x);
setCenterY(event.getSceneY() - y);
// update arrow positions when circles are dragged
for(ArrowSecond arrow : app.getArrows())
arrow.update();
}
});
}
}
抱歉格式错误 - 第一次回答SO问题