【问题标题】:PyQt issue with resizing and repainting of QGraphicsRectItem调整 QGraphicsRectItem 的大小和重新绘制的 PyQt 问题
【发布时间】:2019-03-21 17:43:48
【问题描述】:

我正在尝试创建一个可调整大小的 QGraphicsRectItem,并带有选择不同绘制样式的选项。

如果我创建一个仅具有调整大小功能的简单矩形,那么它会按预期工作:

class Rectangle(QtWidgets.QGraphicsRectItem):
    def __init__(self, x, y, w, h):
        super(Rectangle, self).__init__(0, 0, w, h)
        self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
        self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
            | QtWidgets.QGraphicsItem.ItemIsMovable
            | QtWidgets.QGraphicsItem.ItemIsFocusable
            | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
            | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
        self.setPos(QtCore.QPointF(x, y))

        self.rect = rect = QtCore.QRectF(0, 0, 200, 200)

    def boundingRect(self):
        return self.rect.adjusted(-10, -10, 10, 10)

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            super(Rectangle, self).mouseMoveEvent(event)
        if event.buttons() & QtCore.Qt.RightButton:
            self.rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
            self.prepareGeometryChange()
            self.setRect(self.rect)

当我尝试修改它以更改笔样式和颜色(如果处于活动状态)时,它变得无法选择且无法聚焦。不仅如此,边界矩形出乎意料地消失了。这是修改后的版本:

class Rectangle(QtWidgets.QGraphicsRectItem):
    def __init__(self, position, scene, style=QtCore.Qt.SolidLine,
                 rect=None, matrix=QtGui.QMatrix()):
        super(Rectangle, self).__init__()

        # self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
        self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
                      | QtWidgets.QGraphicsItem.ItemIsMovable
                      | QtWidgets.QGraphicsItem.ItemIsFocusable
                      | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
                      | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)

        if rect is None:
            rect = QtCore.QRectF(0, 0, 200, 200)

        self.size = QtCore.QPointF(200, 200)
        self.rect = rect
        self.style = style
        self.setPos(position)
        self.setMatrix(matrix)

        scene.clearSelection()
        scene.addItem(self)
        self.setSelected(True)
        self.setFocus()
        global RAW
        RAW = True

        self.pen = QtGui.QPen(self.style)
        self.pen.setColor(QtCore.Qt.black)
        self.pen.setWidth(1)

    def parentWidget(self):
        return self.scene().views()[0]

    def boundingRect(self):
        return self.rect.adjusted(-10, -10, 10, 10)

    def paint(self, painter, option, widget):
        if option.state & QtWidgets.QStyle.State_Selected:
            self.pen.setColor(QtCore.Qt.blue)

        painter.setPen(self.pen)
        painter.drawRect(self.rect)

    def itemChange(self, change, variant):
        if change != QtWidgets.QGraphicsItem.ItemSelectedChange:
            global RAW
            RAW = True
        return QtWidgets.QGraphicsItem.itemChange(self, change, variant)

    def contextMenuEvent(self, event):
        wrapped = []
        menu = QtWidgets.QMenu(self.parentWidget())
        for text, param in (("&Solid", QtCore.Qt.SolidLine),
                            ("&Dashed", QtCore.Qt.DashLine),
                            ("D&otted", QtCore.Qt.DotLine),
                            ("D&ashDotted", QtCore.Qt.DashDotLine),
                            ("DashDo&tDotten", QtCore.Qt.DashDotDotLine)):
            wrapper = functools.partial(self.setStyle, param)
            wrapped.append(wrapper)
            menu.addAction(text, wrapper)
        menu.exec_(event.screenPos())

    def setStyle(self, style):
        #self.prepareGeometryChange()
        self.style = style
        self.update()
        global RAW
        RAW = True

    def mousePressEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            super(Rectangle, self).mouseMoveEvent(event)
        if event.buttons() & QtCore.Qt.MiddleButton:
            if self.isSelected():
                self.rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
                self.prepareGeometryChange()
                self.setRect(self.rect)

            global RAW
            RAW = True

我猜主要问题在于重新实现的 paint() 函数,但我仍然没有想出任何想法 在哪里 ...

谁能解释我做错了什么? 哪里出错了,如何让这个东西正常工作?

【问题讨论】:

    标签: python pyqt pyqt5 qgraphicsitem qgraphicsrectitem


    【解决方案1】:

    我的触摸板上没有中间按钮,所以我用右键实现了逻辑,但我给出了一个 10 像素的小边缘,您可以在其中更改矩形的大小。

    要更改样式,您只需更改 QGraphicsItem 的 QPen。

    import functools
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Rectangle(QtWidgets.QGraphicsRectItem):
        def __init__(self, x, y, w, h):
            super(Rectangle, self).__init__(0, 0, w, h)
            self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
            self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
                | QtWidgets.QGraphicsItem.ItemIsMovable
                | QtWidgets.QGraphicsItem.ItemIsFocusable
                | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
                | QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
            self.setPos(QtCore.QPointF(x, y))
    
        def mouseMoveEvent(self, event):
            if event.buttons() & QtCore.Qt.LeftButton:
                super(Rectangle, self).mouseMoveEvent(event)
            if event.buttons() & QtCore.Qt.RightButton:
                rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
                self.prepareGeometryChange()
                self.setRect(rect)
    
        def contextMenuEvent(self, event):
            super(Rectangle, self).contextMenuEvent(event)
            delta = 10
            r = self.boundingRect()
            r.adjust(delta, delta, -delta, -delta)
            if not r.contains(event.pos()):
                return
            self.setSelected(True)
            wrapped = []
            menu = QtWidgets.QMenu(self.parentWidget())
            for text, param in (("&Solid", QtCore.Qt.SolidLine),
                                ("&Dashed", QtCore.Qt.DashLine),
                                ("D&otted", QtCore.Qt.DotLine),
                                ("D&ashDotted", QtCore.Qt.DashDotLine),
                                ("DashDo&tDotten", QtCore.Qt.DashDotDotLine)):
                wrapper = functools.partial(self.setStyle, param)
                wrapped.append(wrapper)
                menu.addAction(text, wrapper)
            menu.exec_(event.screenPos())
    
        def paint(self, painter, option, widget):
            painter.setPen(self.pen())
            painter.setBrush(self.brush())
            if option.state & QtWidgets.QStyle.State_Selected:
                pen = self.pen()
                pen.setColor(QtCore.Qt.blue)
                painter.setPen(pen)
                painter.setBrush(QtCore.Qt.NoBrush)
            painter.drawRect(self.boundingRect())
    
        def setStyle(self, style):
            pen = self.pen()
            pen.setStyle(style)
            self.setPen(pen)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        scene = QtWidgets.QGraphicsScene(-400, -400, 800, 800)
        w = QtWidgets.QGraphicsView(scene)
        scene.addItem(Rectangle(100, 100, 100, 100))
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

      猜你喜欢
      • 2015-04-08
      • 2010-10-03
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      • 2017-11-04
      • 2014-07-28
      • 2014-02-26
      • 1970-01-01
      相关资源
      最近更新 更多