Неправильная работа QSizeGrip

Я написал этот код и он не работает как надо (по моему мнению).
Если вы знаете как сделать так чтобы он заработал как надо, то помогите пожалуйста.

Растягивание как у Qt Dsigner`а, а у меня не пойми как получилось.

Оно должно работать как то так:

Растягивание как у QtDsigner`а

from PyQt5 import QtCore, QtGui, QtWidgets


class SizeGrip(QtWidgets.QSizeGrip):
    def __init__(self, location_angle, parent):
        super().__init__(parent)

        parent.installEventFilter(self)
        self.setFixedSize(30, 30)
        self.location_angle = location_angle

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.Resize:
            if self.location_angle == 'left_top':
                geo = QtCore.QRect(0, 0, 30, 30)
                self.setGeometry(geo)
            elif self.location_angle == 'center_top':
                _geo = self.rect()
                _geo.moveBottomRight(source.rect().bottomRight())
                x = _geo.x() // 2
                geo = QtCore.QRect(x, 0, 30, 30)
                self.setGeometry(geo)
            elif self.location_angle == 'right_top':
                _geo = self.rect()
                _geo.moveBottomRight(source.rect().bottomRight())
                x = _geo.x()
                geo = QtCore.QRect(x, 0, 30, 30)
                self.setGeometry(geo)
            elif self.location_angle == 'left_bottom':
                _geo = self.rect()
                _geo.moveBottomRight(source.rect().bottomRight())
                y = _geo.y()
                geo = QtCore.QRect(0, y, 30, 30)
                self.setGeometry(geo)
            elif self.location_angle == 'right_bottom':
                geo = self.rect()
                geo.moveBottomRight(source.rect().bottomRight())
                self.setGeometry(geo)
        return super().eventFilter(source, event)

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtCore.Qt.white)
        qp.setBrush(QtCore.Qt.red)
        qp.drawRect(QtCore.QRect(10, 10, 10, 10))


class Container(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.sizeGrip1 = SizeGrip('left_top', self)
        self.sizeGrip1_1 = SizeGrip('center_top', self)
        self.sizeGrip2 = SizeGrip('right_top', self)
        self.sizeGrip3 = SizeGrip('left_bottom', self)
        self.sizeGrip4 = SizeGrip('right_bottom', self)

        self.startPos = None
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(20, 20, 20, 20)
        self.setStyleSheet('''
            Container {
                background: lightblue;
                border: 0px;
                border-radius: 4px;
            }
        ''')

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.startPos = event.pos()

    def mouseMoveEvent(self, event):
        if self.startPos:
            self.move(self.pos() + (event.pos() - self.startPos))

    def mouseReleaseEvent(self, event):
        self.startPos = None


class GraphicsRoundedFrame(QtWidgets.QGraphicsProxyWidget):
    def __init__(self):
        super().__init__()

        self.container = Container()
        self.setWidget(self.container)

    def addWidget(self, widget):
        self.container.layout().addWidget(widget)

    def paint(self, qp, opt, widget):
        qp.save()
        p = QtGui.QPainterPath()
        p.addRoundedRect(self.boundingRect().adjusted(0, 0, -.5, -.5), 4, 4)
        qp.setClipPath(p)
        super().paint(qp, opt, widget)
        qp.restore()


class View(QtWidgets.QGraphicsView):
    def __init__(self):
        super().__init__()

        scene = QtWidgets.QGraphicsScene()
        self.setScene(scene)
        self.setRenderHints(QtGui.QPainter.Antialiasing)
        scene.setSceneRect(0, 0, 1024, 768)

        texture = QtGui.QImage(30, 30, QtGui.QImage.Format_ARGB32)
        qp = QtGui.QPainter(texture)
        qp.setBrush(QtCore.Qt.white)
        qp.setPen(QtGui.QPen(QtGui.QColor(189, 190, 191), 2))
        qp.drawRect(texture.rect())
        qp.end()
        scene.setBackgroundBrush(QtGui.QBrush(texture))

        testFrame = GraphicsRoundedFrame()
        scene.addItem(testFrame)
        testFrame.container.layout().addStretch(1)
        testFrame.addWidget(QtWidgets.QPushButton('I am a button'))


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = View()
    w.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Попробуйте так:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class SideGrip(QtWidgets.QWidget):
    def __init__(self, parent, edge):
        QtWidgets.QWidget.__init__(self, parent)
        if edge == QtCore.Qt.LeftEdge:
            self.setCursor(QtCore.Qt.SizeHorCursor)
            self.resizeFunc = self.resizeLeft
        elif edge == QtCore.Qt.TopEdge:
            self.setCursor(QtCore.Qt.SizeVerCursor)
            self.resizeFunc = self.resizeTop
        elif edge == QtCore.Qt.RightEdge:
            self.setCursor(QtCore.Qt.SizeHorCursor)
            self.resizeFunc = self.resizeRight
        else:
            self.setCursor(QtCore.Qt.SizeVerCursor)
            self.resizeFunc = self.resizeBottom
        self.mousePos = None

    def resizeLeft(self, delta):
        window = self.window()
        width = max(window.minimumWidth(), window.width() - delta.x())
        geo = window.geometry()
        geo.setLeft(geo.right() - width)
        window.setGeometry(geo)

    def resizeTop(self, delta):
        window = self.window()
        height = max(window.minimumHeight(), window.height() - delta.y())
        geo = window.geometry()
        geo.setTop(geo.bottom() - height)
        window.setGeometry(geo)

    def resizeRight(self, delta):
        window = self.window()
        width = max(window.minimumWidth(), window.width() + delta.x())
        window.resize(width, window.height())

    def resizeBottom(self, delta):
        window = self.window()
        height = max(window.minimumHeight(), window.height() + delta.y())
        window.resize(window.width(), height)

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.mousePos = event.pos()

    def mouseMoveEvent(self, event):
        if self.mousePos is not None:
            delta = event.pos() - self.mousePos
            self.resizeFunc(delta)

    def mouseReleaseEvent(self, event):
        self.mousePos = None


class Container(QtWidgets.QWidget): 
    _gripSize = 8

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMinimumSize(80, 80) 
        self.sideGrips = [
            SideGrip(self, QtCore.Qt.LeftEdge), 
            SideGrip(self, QtCore.Qt.TopEdge), 
            SideGrip(self, QtCore.Qt.RightEdge), 
            SideGrip(self, QtCore.Qt.BottomEdge), 
        ]
        
        self.cornerGrips = [QtWidgets.QSizeGrip(self) for i in range(4)]
  
        self.resize(300, 200)     
        self.startPos = None
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(20, 20, 20, 20)
        self.setStyleSheet("""
            Container {
                background: lightblue;
                border: 0px;
                border-radius: 4px;
            }
        """)
        
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.startPos = event.pos()

    def mouseMoveEvent(self, event):
        if self.startPos:
            self.move(self.pos() + (event.pos() - self.startPos))

    def mouseReleaseEvent(self, event):
        self.startPos = None        

    @property
    def gripSize(self):
        return self._gripSize

    def setGripSize(self, size):
        if size == self._gripSize:
            return
        self._gripSize = max(2, size)
        self.updateGrips()

    def updateGrips(self):
        self.setContentsMargins(*[self.gripSize] * 4)
        outRect = self.rect()
        inRect = outRect.adjusted(self.gripSize, self.gripSize,
            -self.gripSize, -self.gripSize)

        # top left
        self.cornerGrips[0].setGeometry(
            QtCore.QRect(outRect.topLeft(), inRect.topLeft()))
        # top right
        self.cornerGrips[1].setGeometry(
            QtCore.QRect(outRect.topRight(), inRect.topRight()).normalized())
        # bottom right
        self.cornerGrips[2].setGeometry(
            QtCore.QRect(inRect.bottomRight(), outRect.bottomRight()))
        # bottom left
        self.cornerGrips[3].setGeometry(
            QtCore.QRect(outRect.bottomLeft(), inRect.bottomLeft()).normalized())

        # left edge
        self.sideGrips[0].setGeometry(
            0, inRect.top(), self.gripSize, inRect.height())
        # top edge
        self.sideGrips[1].setGeometry(
            inRect.left(), 0, inRect.width(), self.gripSize)
        # right edge
        self.sideGrips[2].setGeometry(
            inRect.left() + inRect.width(), 
            inRect.top(), self.gripSize, inRect.height())
        # bottom edge
        self.sideGrips[3].setGeometry(
            self.gripSize, inRect.top() + inRect.height(), 
            inRect.width(), self.gripSize)

    def resizeEvent(self, event):
        QtWidgets.QWidget.resizeEvent(self, event)
        self.updateGrips()        


class GraphicsRoundedFrame(QtWidgets.QGraphicsProxyWidget):
    def __init__(self):
        super().__init__()
        self.container = Container()
        self.setWidget(self.container)

    def addWidget(self, widget):
        self.container.layout().addWidget(widget)

    def paint(self, qp, opt, widget):
        qp.save()
        p = QtGui.QPainterPath()
        p.addRoundedRect(self.boundingRect().adjusted(0, 0, -.5, -.5), 4, 4)
        qp.setClipPath(p)
        super().paint(qp, opt, widget)
        qp.restore()


class View(QtWidgets.QGraphicsView):
    def __init__(self):
        super().__init__()

        scene = QtWidgets.QGraphicsScene()
        self.setScene(scene)
        self.setRenderHints(QtGui.QPainter.Antialiasing)
        scene.setSceneRect(0, 0, 1024, 768)

        texture = QtGui.QImage(30, 30, QtGui.QImage.Format_ARGB32)
        qp = QtGui.QPainter(texture)
        qp.setBrush(QtCore.Qt.white)
        qp.setPen(QtGui.QPen(QtGui.QColor(189, 190, 191), 2))
        qp.drawRect(texture.rect())
        qp.end()
        scene.setBackgroundBrush(QtGui.QBrush(texture))

        testFrame = GraphicsRoundedFrame()
        scene.addItem(testFrame)
        testFrame.container.layout().addStretch(1)
        testFrame.addWidget(QtWidgets.QPushButton('I am a button'))


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = View()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка