在节点上绘制箭头

时间:2018-02-01 17:42:06

标签: javafx

我想在网格视图中绘制一组中的箭头。该示例适用于3x3网格。但是,如果我将此大小更改为例如4x4这些箭头位于错误的位置。 我将源字段(绿色)和目标字段(红色)着色以确保我定位正确的单元格。该程序清除arrowGroup并每3秒绘制两个箭头。

GUI working example

import eu.lestard.grid.GridModel;
import eu.lestard.grid.GridView;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

import static javafx.scene.paint.Color.RED;

public class App extends Application {

    private GridView<States> gridView;
    private StackPane stackPane;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane borderPane = new BorderPane();
        stackPane = new StackPane();
        borderPane.setCenter(stackPane);

        Group arrowGroup = new Group();
        GridModel<States> gridModel = new GridModel<>();

        gridModel.setDefaultState(States.EMPTY);
        gridModel.setNumberOfColumns(3);
        gridModel.setNumberOfRows(3);

        gridView = new GridView<>();
        gridView.setGridModel(gridModel);

        stackPane.getChildren().add(gridView);
        stackPane.getChildren().add(arrowGroup);

        final Scene scene = new Scene(borderPane, 500, 500);

        primaryStage.setScene(scene);
        primaryStage.show();

        new Thread(() -> {
            for (int i = 1; i <= 1000000; i++) {
                Platform.runLater( () -> {
                    arrowGroup.getChildren().clear();
                    drawArrow(arrowGroup, new Point2D(0,0), new Point2D(2,1));
                    drawArrow(arrowGroup, new Point2D(1,1), new Point2D(0,2));
                });
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            }).start();
    }

    // getRelativeBounds, getCenter based on https://stackoverflow.com/a/43119383/772883
    private void drawArrow(Group group, Point2D from, Point2D to) {
        final Line line = new Line();

        System.out.println(String.format("Draw arrow from cell %s to %s", from, to));
        System.out.println(String.format("group coord %s %s", group.getLayoutX(), group.getLayoutY()));

        // Note: (X,Y) -> (Column, Row) => access via (Y,X)
        final Pane cellPane = gridView.getCellPane(gridView.getGridModel().getCell(((int) from.getY()), (int) from.getX() ));
        final Pane cellPane2 = gridView.getCellPane(gridView.getGridModel().getCell((int) to.getY() , (int) to.getX()));

        cellPane.setBackground(new Background(new BackgroundFill(Color.DARKGREEN, CornerRadii.EMPTY, Insets.EMPTY)));
        cellPane2.setBackground(new Background(new BackgroundFill(RED, CornerRadii.EMPTY, Insets.EMPTY)));

        Bounds n1InCommonAncestor = getRelativeBounds(cellPane, gridView);
        Bounds n2InCommonAncestor = getRelativeBounds(cellPane2, gridView);

        Point2D n1Center = getCenter(n1InCommonAncestor);
        Point2D n2Center = getCenter(n2InCommonAncestor);

        System.out.println(String.format("Draw arrow from coord %s to %s", n1Center, n2Center));

        System.out.println(n1Center);
        System.out.println(n2Center);

        line.setStartX(n1Center.getX());
        line.setStartY(n1Center.getY());
        line.setEndX(n2Center.getX());
        line.setEndY(n2Center.getY());
        group.getChildren().add(line);
    }

    private Bounds getRelativeBounds(Node node, Node relativeTo) {
        Bounds nodeBoundsInScene = node.localToScene(node.getBoundsInLocal());
        return relativeTo.sceneToLocal(nodeBoundsInScene);
    }

    private Point2D getCenter(Bounds b) {
        return new Point2D(b.getMinX() + b.getWidth() / 2, b.getMinY() + b.getHeight() / 2);
    }

    public static enum States {
        EMPTY,
        X,
        O
    }
}

(如果已用线代替箭头以减少代码。)

代码和gradle构建文件有一个要点: https://gist.github.com/anonymous/c54b12ee04b7e45f2e9f58e9de1d1df0

如果有人能够解释为什么只适用于3x3,那将会很棒。有没有比团体更好的选择?

0 个答案:

没有答案
相关问题