iRex
24th August 2017, 19:24
Hello everyone! This is my first post here. Using search I found that here, one can post PyQt questions but I'm using PySide. I don't know If I'm breaking the rules of this forum. If so I ask moderators to remove this post.
I'm very new in programming and never used C++ but writing this code my guide was QT documentation because it is more descriptive than PyQt.
What I'm looking for is to create node graph kind of UI. I have realized nodes and connections. It works fine with two items connected in the scene but when I create two more nodes it does not work properly. I mean if you create two nodes with double click, then select them and do right click you'll see a path between this two nodes. If you move one of the node the pathElements will follow the nodes. Now add two more nodes and connect them. You'll see that newly created path does not transform.
Double click = creates nodes. Selecting 2 nodes and right click creates path item between 2 selected items.
Here is the code:
from PySide.QtCore import *
from PySide.QtGui import *
rad = 5
class WindowClass(QMainWindow):
def __init__(self):
super(WindowClass, self).__init__()
self.view = ViewClass()
self.setCentralWidget(self.view)
class ViewClass(QGraphicsView):
def __init__(self):
super(ViewClass, self).__init__()
self.setDragMode(QGraphicsView.RubberBandDrag)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwa ysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlways Off)
self.s = SceneClass()
self.setScene(self.s)
self.setRenderHint(QPainter.Antialiasing)
class SceneClass(QGraphicsScene):
def __init__(self, id=None):
super(SceneClass, self).__init__()
self.setSceneRect(-1000, -1000, 2000, 2000)
self.grid = 30
self.it = None
self.node = None
def drawBackground(self, painter, rect):
if False:
painter = QPainter()
rect = QRect()
painter.fillRect(rect, QColor(30, 30, 30))
left = int(rect.left()) - int((rect.left()) % self.grid)
top = int(rect.top()) - int((rect.top()) % self.grid)
right = int(rect.right())
bottom = int(rect.bottom())
lines = []
for x in range(left, right, self.grid):
lines.append(QLine(x, top, x, bottom))
for y in range(top, bottom, self.grid):
lines.append(QLine(left, y, right, y))
painter.setPen(QPen(QColor(50, 50, 50)))
painter.drawLines(lines)
def addNode(self, pos=False):
if not pos:
pos = QPoint(0, 0)
item = ItemClass(self.grid, len(self.items()))
self.addItem(item)
item.setPos(pos)
def mouseDoubleClickEvent(self, event):
self.addNode(event.scenePos())
super(SceneClass, self).mouseDoubleClickEvent(event)
def mousePressEvent(self, event):
if event.button() == Qt.RightButton:
self._start = event.scenePos()
#####
path = QPainterPath()
path.moveTo(self.selectedItems()[0].pos().x(), self.selectedItems()[0].pos().y())
path.lineTo(self.selectedItems()[1].pos().x(), self.selectedItems()[1].pos().y())
item = Path(path, self)
self.selectedItems()[0].linkToItem = item
self.selectedItems()[1].linkToItem = item
self.addItem(item)
super(SceneClass, self).mousePressEvent(event)
class Path(QGraphicsPathItem):
def __init__(self, path, scene):
super(Path, self).__init__(path)
self.setPen(QPen(Qt.red, 1.75))
def updateElement(self, index, pos):
path = self.path()
path.setElementPositionAt(index, pos.x(), pos.y())
self.setPath(path)
class ItemClass(QGraphicsItem):
def __init__(self, height, index ):
super(ItemClass, self).__init__()
self.x = 0
self.y = 0
self.w = 150
self.h = height
self.hover = None
self.setAcceptHoverEvents(True)
self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemSendsGeometryChange s)
self.linkToItem = None
self.index = index
self.setZValue(1)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
if self.linkToItem:
self.linkToItem.updateElement(self.index, value)
return QGraphicsItem.itemChange(self, change, value)
def boundingRect(self):
return QRect(self.x, self.y, self.w, self.h)
def paint(self, painter, opt, w):
rec = self.boundingRect()
if False:
painter = QPainter()
if not self.hover:
color = Qt.darkGray
else:
color = Qt.gray
if self.isSelected():
color = Qt.yellow
painter.fillRect(rec.adjusted(3,3,-3,-3),color)
self.scene().update()
if __name__ == '__main__':
app = QApplication([])
wd = WindowClass()
wd.show()
app.exec_()
I'm very new in programming and never used C++ but writing this code my guide was QT documentation because it is more descriptive than PyQt.
What I'm looking for is to create node graph kind of UI. I have realized nodes and connections. It works fine with two items connected in the scene but when I create two more nodes it does not work properly. I mean if you create two nodes with double click, then select them and do right click you'll see a path between this two nodes. If you move one of the node the pathElements will follow the nodes. Now add two more nodes and connect them. You'll see that newly created path does not transform.
Double click = creates nodes. Selecting 2 nodes and right click creates path item between 2 selected items.
Here is the code:
from PySide.QtCore import *
from PySide.QtGui import *
rad = 5
class WindowClass(QMainWindow):
def __init__(self):
super(WindowClass, self).__init__()
self.view = ViewClass()
self.setCentralWidget(self.view)
class ViewClass(QGraphicsView):
def __init__(self):
super(ViewClass, self).__init__()
self.setDragMode(QGraphicsView.RubberBandDrag)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwa ysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlways Off)
self.s = SceneClass()
self.setScene(self.s)
self.setRenderHint(QPainter.Antialiasing)
class SceneClass(QGraphicsScene):
def __init__(self, id=None):
super(SceneClass, self).__init__()
self.setSceneRect(-1000, -1000, 2000, 2000)
self.grid = 30
self.it = None
self.node = None
def drawBackground(self, painter, rect):
if False:
painter = QPainter()
rect = QRect()
painter.fillRect(rect, QColor(30, 30, 30))
left = int(rect.left()) - int((rect.left()) % self.grid)
top = int(rect.top()) - int((rect.top()) % self.grid)
right = int(rect.right())
bottom = int(rect.bottom())
lines = []
for x in range(left, right, self.grid):
lines.append(QLine(x, top, x, bottom))
for y in range(top, bottom, self.grid):
lines.append(QLine(left, y, right, y))
painter.setPen(QPen(QColor(50, 50, 50)))
painter.drawLines(lines)
def addNode(self, pos=False):
if not pos:
pos = QPoint(0, 0)
item = ItemClass(self.grid, len(self.items()))
self.addItem(item)
item.setPos(pos)
def mouseDoubleClickEvent(self, event):
self.addNode(event.scenePos())
super(SceneClass, self).mouseDoubleClickEvent(event)
def mousePressEvent(self, event):
if event.button() == Qt.RightButton:
self._start = event.scenePos()
#####
path = QPainterPath()
path.moveTo(self.selectedItems()[0].pos().x(), self.selectedItems()[0].pos().y())
path.lineTo(self.selectedItems()[1].pos().x(), self.selectedItems()[1].pos().y())
item = Path(path, self)
self.selectedItems()[0].linkToItem = item
self.selectedItems()[1].linkToItem = item
self.addItem(item)
super(SceneClass, self).mousePressEvent(event)
class Path(QGraphicsPathItem):
def __init__(self, path, scene):
super(Path, self).__init__(path)
self.setPen(QPen(Qt.red, 1.75))
def updateElement(self, index, pos):
path = self.path()
path.setElementPositionAt(index, pos.x(), pos.y())
self.setPath(path)
class ItemClass(QGraphicsItem):
def __init__(self, height, index ):
super(ItemClass, self).__init__()
self.x = 0
self.y = 0
self.w = 150
self.h = height
self.hover = None
self.setAcceptHoverEvents(True)
self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemSendsGeometryChange s)
self.linkToItem = None
self.index = index
self.setZValue(1)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
if self.linkToItem:
self.linkToItem.updateElement(self.index, value)
return QGraphicsItem.itemChange(self, change, value)
def boundingRect(self):
return QRect(self.x, self.y, self.w, self.h)
def paint(self, painter, opt, w):
rec = self.boundingRect()
if False:
painter = QPainter()
if not self.hover:
color = Qt.darkGray
else:
color = Qt.gray
if self.isSelected():
color = Qt.yellow
painter.fillRect(rec.adjusted(3,3,-3,-3),color)
self.scene().update()
if __name__ == '__main__':
app = QApplication([])
wd = WindowClass()
wd.show()
app.exec_()