Created
September 18, 2017 19:12
-
-
Save YoelShoshan/b5c1f24584f913f5a3841eebb8468a9d to your computer and use it in GitHub Desktop.
simple standalone script for pyside + networx + graphviz layout of an acyclic directed graph
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt4.QtGui import * | |
from PyQt4.QtCore import * | |
import networkx as nx | |
from networkx.drawing.nx_agraph import graphviz_layout | |
class ZedNode(QGraphicsEllipseItem): | |
rad = 5 | |
def __init__(self, key): | |
super().__init__(-ZedNode.rad, -ZedNode.rad, 2*ZedNode.rad, 2*ZedNode.rad) | |
self.rad = ZedNode.rad | |
#self.path = path | |
self.key = key | |
self.setZValue(1) | |
self.setFlag(QGraphicsItem.ItemIsMovable) | |
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) | |
self.setBrush(Qt.green) | |
self.edges = [] | |
self.end_of_edges = [] | |
self.start_of_edges = [] | |
def addParticipatingInEdges(self, zed_edge): | |
self.edges.append(zed_edge) | |
if zed_edge.start_node == self: | |
self.start_of_edges.append(zed_edge) | |
elif zed_edge.end_node == self: | |
self.end_of_edges.append(zed_edge) | |
else: | |
assert False | |
def itemChange(self, change, value): | |
#if change == QGraphicsItem.ItemPositionChange: | |
# if type(value)==QPointF: | |
# self.path.updateElement(self.index, value) | |
# else: | |
# self.path.updateElement(self.index, value.toPointF()) | |
if change == QGraphicsItem.ItemPositionChange: | |
if type(value) == QPointF: | |
fixed_val = value | |
else: | |
fixed_val = value.toPointF() | |
for edge in self.start_of_edges: | |
edge.updateElement(0,fixed_val) | |
for edge in self.end_of_edges: | |
edge.updateElement(1,fixed_val) | |
return QGraphicsEllipseItem.itemChange(self, change, value) | |
class ZedEdge(QGraphicsPathItem): | |
def __init__(self, start_node, end_node): | |
self.start_node = start_node | |
self.end_node = end_node | |
self.ppath = QPainterPath() | |
start_node_pos = start_node.scenePos() | |
end_node_pos = end_node.scenePos() | |
self.ppath.moveTo(start_node_pos) | |
self.ppath.lineTo(end_node_pos) | |
#gfx_path = QGraphicsPathItem(ppath) | |
#scene.addItem(gfx_path) | |
return super().__init__(self.ppath) | |
def updateElement(self, index, pos): | |
self.ppath.setElementPositionAt(index, pos.x(), pos.y()) | |
self.setPath(self.ppath) | |
if __name__ == "__main__": | |
app = QApplication([]) | |
scene = QGraphicsScene() | |
def test_graph_1(): | |
G = nx.DiGraph(directed=True) | |
G.add_edge("root", "1") | |
G.add_edge("root", "2") | |
G.add_edge("root", "3") | |
G.add_edge("1", "11") | |
G.add_edge("11", "111") | |
G.add_edge("111", "1111") | |
G.add_edge("11", "22") | |
G.add_edge("22", "222") | |
return G | |
G = test_graph_1() | |
nodes_pos = graphviz_layout(G) | |
zed_nodes = {} #maps from node key (unique id) to ZedNode instance | |
#add nodes | |
for k,val in nodes_pos.items(): | |
node = ZedNode(k) | |
node.setPos(QPointF(val[0],val[1])) | |
scene.addItem(node) | |
zed_nodes[k] = node | |
#add edges | |
for edge in G.in_edges(): | |
start_node_id, end_node_id = edge[0], edge[1] | |
node_start = zed_nodes[start_node_id] | |
node_end = zed_nodes[end_node_id] | |
edge = ZedEdge(node_start, node_end) | |
scene.addItem(edge) | |
node_start.addParticipatingInEdges(edge) | |
node_end.addParticipatingInEdges(edge) | |
view = QGraphicsView(scene) | |
view.setRenderHint(QPainter.Antialiasing) | |
view.resize(600, 400) | |
view.show() | |
app.exec_() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment