JavaFX正确绘制节点之间的线

时间:2018-07-25 19:26:55

标签: javafx layout graph drawing line

我正在尝试为JavaFX中的图形开发一个简单的编辑器。 我从这篇帖子Graph like yFiles中删除了RolandC的解决方案,并尝试进一步开发。

现在我有两个问题:

  1. 我想通过将鼠标从一个拖到另一个来在节点之间添加边缘。这样做时,我想用鼠标画一条线。

我通过添加onDragDetected-,onMouseDragged-和onMouseDragReleased-EventHandlers来实现此目的。问题在于该线不在节点之间画线,而是在应用程序的其他地方画线。但是,当我在另一个节点上释放鼠标时,将正确绘制Edge。

此处提供事件处理代码:

public class MouseGestures {
final DragContext dragContext = new DragContext();

Graph graph;
Line line;

public MouseGestures(Graph graph) {
    this.graph = graph;
}

public void makeDraggable(final Node node) {

    node.setOnMousePressed(onMousePressedEventHandler);
    node.setOnMouseDragged(onMouseDraggedEventHandler);
    node.setOnDragDetected(onDragDetectedHandler);
    node.setOnMouseDragReleased(onMouseDragReleased);
    graph.getCellLayer().setOnMouseDragReleased(onMouseDragReleased);


}


EventHandler<MouseEvent> onDragDetectedHandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        if (!event.isPrimaryButtonDown() && event.isSecondaryButtonDown()) {
            if (line == null) {
                line = new Line();
                line.setStartX(event.getSceneX());
                line.setStartY(event.getSceneY());
                line.setEndX(event.getSceneX());
                line.setEndY(event.getSceneY());
                graph.getCellLayer().getChildren().add(0,line);
                Node node = (Node) event.getSource();
                node.startFullDrag();
            }
        }
    }
};


EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {

    @Override
    public void handle(MouseEvent event) {
        if (event.isPrimaryButtonDown() && !event.isSecondaryButtonDown()) {
            Node node = (Node) event.getSource();

            double scale = graph.getScale();

            dragContext.x = node.getBoundsInParent().getMinX() * scale - event.getScreenX();
            dragContext.y = node.getBoundsInParent().getMinY() * scale - event.getScreenY();
        }
    }
};

EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {

    @Override
    public void handle(MouseEvent event) {
        if (event.isPrimaryButtonDown() && !event.isSecondaryButtonDown()) {
            Node node = (Node) event.getSource();

            double offsetX = event.getScreenX() + dragContext.x;
            double offsetY = event.getScreenY() + dragContext.y;

            // adjust the offset in case we are zoomed
            double scale = graph.getScale();

            offsetX /= scale;
            offsetY /= scale;

            node.relocate(offsetX, offsetY);
        } else if (!event.isPrimaryButtonDown() && event.isSecondaryButtonDown()) {
            if (line != null) {
                line.setEndX(event.getSceneX());
                line.setEndY(event.getSceneY());
            }
        }
    }
};


EventHandler<MouseDragEvent> onMouseDragReleased = new EventHandler<MouseDragEvent>() {
    @Override
    public void handle(MouseDragEvent event) {

        System.out.println(event.getSource());
        System.out.println(event.getGestureSource());
        if (event.getSource() != event.getGestureSource()) {
            System.out.println(event.getSource().getClass());
            if (event.getSource() instanceof Cell) {
                Cell source = (Cell) event.getGestureSource();
                Cell target = (Cell) event.getSource();
                graph.getModel().addEdge(source.getCellId(), target.getCellId());
                graph.endUpdate();

            }
            graph.getCellLayer().getChildren().remove(line);
            line = null;
        }
    }
};


class DragContext {
    double x;
    double y;

}

}

Error drawing lines显示了问题:我用鼠标在节点“ action1”上开始,并且该行从屏幕上的其他地方开始。 有人知道这里出什么问题吗?

  1. 初始边缘绘制不正确。

我向我的GraphModel和一些边添加了一些单元格。但是,尽管我的代码将边缘绑定到单元格的中心,但边缘却与单元格的左上角相连,而不是与中心相连。

边缘代码:

public Edge(Cell source, Cell target) {

    this.source = source;
    this.target = target;

    source.addCellChild(target);
    target.addCellParent(source);

    line = new Line();

    line.startXProperty().bind( source.layoutXProperty().add(source.getBoundsInParent().getWidth() / 2.0));
    line.startYProperty().bind( source.layoutYProperty().add(source.getBoundsInParent().getHeight() / 2.0));

    line.endXProperty().bind( target.layoutXProperty().add( target.getBoundsInParent().getWidth() / 2.0));
    line.endYProperty().bind( target.layoutYProperty().add( target.getBoundsInParent().getHeight() / 2.0));

    getChildren().add( line);

}

我在其中添加单元格和边的代码:

        Graph graph = new Graph();                                     

    contentPane.setCenter(graph.getScrollPane());                  


    testGraph(graph);                                              
    Layout layout = new AbegoTreeLayout(graph);                    
    layout.execute();                                              



}                                                                  

private void testGraph(Graph graph){                               
    GraphModel model = graph.getModel();                           

    graph.beginUpdate();                                           

    model.addCell("action1","action1",CellType.ACTION);            
    model.addCell("action2","action2",CellType.ACTION);            
    model.addCell("action3","action3",CellType.ACTION);            

    model.addEdge("action1","action2");                            

    model.addEdge("action1","action3");                            

    graph.endUpdate();                                             

和TreeLayout的代码:

public class AbegoTreeLayout extends Layout{

private final Configuration<Cell> configuration;
Graph graph;
public AbegoTreeLayout(Graph graph){

    this(graph ,100,45, Location.Top);

}

public AbegoTreeLayout(Graph graph,double gapBetweenLevels, double gapBetweenNodes, Location location) {
    this(new DefaultConfiguration<>(gapBetweenLevels, gapBetweenNodes, location),graph);
}

public AbegoTreeLayout(Configuration<Cell> configuration, Graph graph) {
    this.configuration = configuration;
    this.graph = graph;
}


@Override
public void execute() {
    final DefaultTreeForTreeLayout<Cell> layout = new DefaultTreeForTreeLayout<>(graph.getModel().getGraphParent());
    addRecursively(layout,graph.getModel().getGraphParent());

    final NodeExtentProvider<Cell> nodeExtentProvider = new NodeExtentProvider<Cell>() {
        @Override
        public double getWidth(Cell element) {
            if(element == graph.getModel().getGraphParent()){
                return 0;
            }
            return element.getWidth();
        }

        @Override
        public double getHeight(Cell element) {
            if(element == graph.getModel().getGraphParent()){
                return 0;
            }
            return element.getHeight();
        }
    };

    final TreeLayout<Cell> treeLayout = new TreeLayout<>(layout,nodeExtentProvider,configuration);


    treeLayout.getNodeBounds().entrySet().stream().filter(entry -> entry.getKey() != graph.getModel().getGraphParent()).forEach(entry -> {
        entry.getKey().relocate(entry.getValue().getX(),entry.getValue().getY());
    });



}


public void addRecursively(DefaultTreeForTreeLayout<Cell> layout, Cell node) {
    node.getCellChildren().forEach(element -> {
        if(!layout.hasNode(element)) {
            layout.addChild(node, element);
            addRecursively(layout, element);
        }
    });
}

}

我真的不明白为什么Edge-Lines没有与中心连接... 可以在图片上看到。

非常感谢您尝试提供的帮助。

0 个答案:

没有答案