java - 圆圈边缘的箭头

标签 java javafx javafx-8

在下面的 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();
            }
        });
    }
}

最佳答案

这是我的解决方案:

我根据节点的半径减去了结束 X 和结束 Y 坐标。数学非常简单 - 我只是从斜边中减去一个比率。

测试箭头类:

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

箭头第二类:

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

anchor 二类:

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

抱歉格式错误 - 第一次回答这样的问题

关于java - 圆圈边缘的箭头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34021482/

相关文章:

java - 无法添加 CSS 文件

java - 如何在 JavaFX 中从数据库创建自定义 LookUp 搜索小部件

java - 如何双向绑定(bind)到设置为 TableView 的所选项目属性的对象的属性?

java - 根据条件分组/不同列

java - H2 未在我的 Spring Boot 应用程序中创建/更新表。我的实体有问题吗?

java - ObjectName 与 String FindBug 错误不兼容

JavaFx 日期小部件

JavaFX:FXML 中导入类的 ClassNotFoundException

java - 限制 JavaFX TextField 的字符数导致撤消时出现 IndexOutOfBounds

java - 构建多文物以进行Vaadin应用[Gradle]