我正在尝试为JavaFX中的图形开发一个简单的编辑器。 我从这篇帖子Graph like yFiles中删除了RolandC的解决方案,并尝试进一步开发。
现在我有两个问题:
我通过添加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;
}
}
显示了问题:我用鼠标在节点“ action1”上开始,并且该行从屏幕上的其他地方开始。 有人知道这里出什么问题吗?
我向我的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没有与中心连接... 可以在图片上看到。
非常感谢您尝试提供的帮助。