Python 在Graphicscene中通过鼠标动作和鼠标事件使GraphicSites可编辑

Python 在Graphicscene中通过鼠标动作和鼠标事件使GraphicSites可编辑,python,pyqt,pyqt5,qgraphicsview,Python,Pyqt,Pyqt5,Qgraphicsview,我目前正在编写一个交互式GUI,下面的代码通过鼠标事件连续插入节点和各自的边,通过双击事件开始和结束绘图会话(基于本文)。我想使节点和边可以编辑,因为在绘制之后,用户可以通过鼠标事件在节点位置周围移动,如下面的示例所示。 , 代码 class WindowClass(QMainWindow): def __init__(self, parent=None): super(WindowClass, self).__init__(parent) view =

我目前正在编写一个交互式GUI,下面的代码通过鼠标事件连续插入节点和各自的边,通过双击事件开始和结束绘图会话(基于本文)。我想使节点和边可以编辑,因为在绘制之后,用户可以通过鼠标事件在节点位置周围移动,如下面的示例所示。 ,

代码

class WindowClass(QMainWindow):
    def __init__(self, parent=None):
        super(WindowClass, self).__init__(parent)
        view = QGraphicsView()
        view.setMouseTracking(True)
        view.setRenderHint(QPainter.Antialiasing)
        scene = SceneClass(self)
        view.setScene(scene)
        self.setCentralWidget(view)
        self.resize(640, 480)

class SceneClass(QGraphicsScene):
    def __init__(self, parent=None):
        super(SceneClass, self).__init__(QRectF(-1000, -1000, 2000, 2000), parent)
        self._edge_item = None
        self.pos = None
        self.pos_end = None
        self.node_start = None
        self.node_end = None

    def mouseDoubleClickEvent(self, event):
        if event.button() == Qt.LeftButton:
            "Agregar Nodo"
            self.node_start = Node()
            self.node_start.setPos(event.scenePos())
            self.addItem(self.node_start)
            "Agregar Edge"
            self._edge_item = Edge()
            self._edge_item.src = self.node_start
            self.addItem(self._edge_item)
            if self.node_end:
                self.node_end = None
                self.node_start = None

            self.node_end = self.node_start

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and self.node_end:
            "Agregar Nodo"
            self.node_start = Node()
            self.node_start.setPos(event.scenePos())
            self.addItem(self.node_start)
            self.node_end = self.node_start
            "Agregar Edge"
            self._edge_item = Edge()
            self._edge_item.src = self.node_start
            self.addItem(self._edge_item)

    def mouseMoveEvent(self, event):
        if self._edge_item and self.node_end:
            self._edge_item.p1 = event.scenePos()
        super(SceneClass, self).mouseMoveEvent(event)

class Node(QGraphicsEllipseItem):
    def __init__(self, rect=QRectF(-10, -10, 20, 20), parent=None):
        super(Node, self).__init__(rect, parent)
        self.edges = []
        self.setZValue(1)
        self.setBrush(Qt.darkGray)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)

    def addEdge(self, edge):
        self.edges.append(edge)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedChange:
            self.setBrush(Qt.green if value else Qt.darkGray)
        if change == QGraphicsItem.ItemPositionHasChanged:
            for edge in self.edges:
                edge.adjust()
        return super(Node, self).itemChange(change, value)

class Edge(QGraphicsLineItem):
    def __init__(self, parent=None):
        super(Edge, self).__init__(parent)
        self.setPen(QPen(Qt.red, 3))
        self._src = None
        self._dst = None

    @property
    def src(self):
        return self._src

    @src.setter
    def src(self, node):
        self._src = node
        self._src.addEdge(self)
        self.adjust()

    @property
    def dst(self):
        return self._dst

    @dst.setter
    def dst(self, node):
        self._dst = node
        self._dst.addEdge(self)
        self.adjust()

    @property
    def p1(self):
        return self.line().p1()

    @p1.setter
    def p1(self, p):
        line = self.line()
        line.setP1(p)
        self.setLine(line)

    @property
    def p2(self):
        return self.line().p2()

    @p2.setter
    def p2(self, p):
        line = self.line()
        line.setP2(p)
        self.setLine(line)

    def adjust(self):
        self.prepareGeometryChange()
        if self.src:
            self.p1 = self.src.pos()
            self.p2 = self.src.pos()
        if self.dst:
            self.p2 = self.dst.pos()

我试图通过在edge类中添加一个hoover事件来启动,但是在设置为accept hover event并创建一个函数来指示对该事件的操作之后,该函数不会触发

OP的逻辑不正确,因此我不得不对其进行一些修改,使其正确地遵循顺序

另一方面,默认情况下已经实现了移动项目的行为,但是有必要将鼠标事件发送到项目,为此,有必要调用mouseXEvent方法的super()方法

类场景类(qgraphicscene):
def uuu init uuu(self,parent=None):
超级(场景类,self)。\uuuuu初始化(QRectF(-1000,-100020002000),父级)
self.\u edge\u item=无
self.\u last\u节点=无
def mouseDoubleClickEvent(自身,事件):
如果event.button()==Qt.LeftButton:
如果是self.\u last\u节点:
self.\u last\u节点=无
self.\u edge\u item=无
其他:
node=node()
node.setPos(event.scenePos())
self.addItem(节点)
self.\u edge\u item=edge()
self.\u edge\u item.src=节点
自我添加项(自我边缘项)
self.\u last\u node=节点
返回
超级(场景类,自我)。鼠标双击事件(事件)
def鼠标压力事件(自身、事件):
如果event.button()==Qt.LeftButton和self.\u last\u节点:
node=node()
node.setPos(event.scenePos())
self.addItem(节点)
self._edge_item.dst=节点
self.\u edge\u item=edge()
self.\u edge\u item.src=节点
自我添加项(自我边缘项)
self.\u last\u node=节点
返回
超级(场景类,自我)。鼠标压力事件(事件)
def mouseMoveEvent(自身、事件):
如果是自边项目:
self.\u edge\u item.p1=event.scenePos()
超级(场景类,自我)。mouseMoveEvent(事件)
类节点(QGraphicsSellipseitem):
定义初始化(self,rect=QRectF(-10,-10,20,20),父项=None):
超级(节点,自身)。\uuuu初始化\uuuuuuuuuuuu(矩形,父级)
self.edges=[]
自我设置值(1)
自我挫折(Qt.darkGray)
self.setFlag(QGraphicsItem.ItemIsMovable,True)
self.setFlag(QGraphicsItem.ItemIsSelectable,True)
self.setFlag(QGraphicsItem.itemssendsgeometrychanges,True)
def addEdge(自身、边缘):
self.edges.append(边)
def itemChange(自身、更改、值):
如果change==QGraphicsItem.ItemSelectedChange:
self.setBrush(Qt.green如果值为else Qt.darkGray)
如果更改==QGraphicsItem.ItemPositionHasChanged:
对于self.edges中的边:
edge.adjust()
返回超级(节点,自身).itemChange(更改,值)
类边(QGraphicsLineItem):
def uuu init uuu(self,parent=None):
超级(边,自).\uuuu初始化\uuuu(父级)
自动设置笔(QPen(Qt.red,3))
self.\u src=无
self._dst=无
@财产
def src(自我):
返回自我。\u src
@src.setter
def src(自身,节点):
self.\u src=节点
自我补充(自我)
自我调整
@财产
def dst(自我):
返回自我
@dst.setter
def dst(自身、节点):
self._dst=节点
自我添加(自我)
自我调整
@财产
def p1(自我):
返回self.line().p1()
@p1.setter
def p1(自身,p):
line=self.line()
第1行设置P1(p)
self.setLine(行)
@财产
def p2(自我):
返回self.line().p2()
@p2.setter
def p2(自身,p):
line=self.line()
第2行设置P2(p)
self.setLine(行)
def调整(自):
self.prepareGeometryChange()
如果self.src:
self.p1=self.src.pos()
self.p2=self.src.pos()
如果self.dst:
self.p2=self.dst.pos()

OP的逻辑不正确,因此我不得不稍微修改它,使其正确地遵循顺序

另一方面,默认情况下已经实现了移动项目的行为,但是有必要将鼠标事件发送到项目,为此,有必要调用mouseXEvent方法的super()方法

类场景类(qgraphicscene):
def uuu init uuu(self,parent=None):
超级(场景类,self)。\uuuuu初始化(QRectF(-1000,-100020002000),父级)
self.\u edge\u item=无
self.\u last\u节点=无
def mouseDoubleClickEvent(自身,事件):
如果event.button()==Qt.LeftButton:
如果是self.\u last\u节点:
self.\u last\u节点=无
self.\u edge\u item=无
其他:
node=node()
node.setPos(event.scenePos())
self.addItem(节点)
self.\u edge\u item=edge()
self.\u edge\u item.src=节点
自我添加项(自我边缘项)
self.\u last\u node=节点
返回
超级(场景类,自我)。鼠标双击事件(事件)
def鼠标压力事件(自身、事件):
如果event.button()==Qt.LeftButton和self.\u last\u节点:
node=node()
node.setPos(event.scenePos())
self.addItem(节点)
self._edge_item.dst=节点
self.\u edge\u item=edge()
self.\u edge\u item.src=节点
自我添加项(自我边缘项)
self.\u last\u node=节点
返回