使GraphicsItem可通过Graphicscene中的鼠标动作和鼠标事件进行编辑

问题描述 投票:0回答:1

我当前正在编写一个交互式GUI,下面的代码通过鼠标事件通过进行双击事件来开始和结束绘制会话,从而以连续的方式插入节点和各个边缘(基于此文章Join QGraphicsItem and QPainter in same GraphicsScene)。我想使节点和边缘可编辑,因为在绘制之后用户可以通过鼠标事件在节点位置周围移动,如以下示例所示。how to use QGraphicsView::RubberBandDrag?

代码

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()

我试图通过在边缘类中添加一个悬停事件来启动,但是在设置为接受悬停事件并创建一个函数来指示对此事件进行操作后,此函数不会触发。

python pyqt pyqt5 qgraphicsview
1个回答
2
投票
OP的逻辑不正确,所以我不得不对其进行一些修改,以使其正确地遵循顺序。

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

class SceneClass(QGraphicsScene): def __init__(self, parent=None): super(SceneClass, self).__init__(QRectF(-1000, -1000, 2000, 2000), parent) self._edge_item = None self._last_node = None def mouseDoubleClickEvent(self, event): if event.button() == Qt.LeftButton: if self._last_node: self._last_node = None self._edge_item = None else: node = Node() node.setPos(event.scenePos()) self.addItem(node) self._edge_item = Edge() self._edge_item.src = node self.addItem(self._edge_item) self._last_node = node return super(SceneClass, self).mouseDoubleClickEvent(event) def mousePressEvent(self, event): if event.button() == Qt.LeftButton and self._last_node: node = Node() node.setPos(event.scenePos()) self.addItem(node) self._edge_item.dst = node self._edge_item = Edge() self._edge_item.src = node self.addItem(self._edge_item) self._last_node = node return super(SceneClass, self).mousePressEvent(event) def mouseMoveEvent(self, event): if self._edge_item: 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()

© www.soinside.com 2019 - 2024. All rights reserved.