Есть ли виджеты в PyQt5, размер которых может изменять пользователь?

Мне нужен виджет, как бы рамочка, размер которого может изменять сам пользователь также, как он может изменять размер окна.

Но я даже не уверена есть ли такое вообще.


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

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

Один из способ изменить размер виджета - использовать QSizeGrip.

Класс QSizeGrip предоставляет дескриптор изменения размера для изменения размеров окон верхнего уровня.
Больше https://doc.qt.io/qt-5/qsizegrip.html

Обратите внимание, что QSizeGrip не следует добавлять в макет, и его всегда следует перемещать вручную в соответствии с его угловым положением и размером его родительского элемента.

from PyQt5 import QtCore, QtGui, QtWidgets


class SizeGrip(QtWidgets.QSizeGrip):
    def __init__(self, parent):
        super().__init__(parent)
        
        parent.installEventFilter(self)
        self.setFixedSize(30, 30)
        self.polygon = QtGui.QPolygon([
            QtCore.QPoint(10, 20), 
            QtCore.QPoint(20, 10), 
            QtCore.QPoint(20, 20), 
        ])

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.Resize:
            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)           # QtCore.Qt.gray
        qp.drawPolygon(self.polygon)


class Container(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.sizeGrip = SizeGrip(self)
        
        self.startPos = None
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(6, 6, 6, 30)
        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)
        self.label_2 = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
        self.label_2.setPixmap(QtGui.QPixmap("lena.jpg").scaled(100, 100))
        testFrame.addWidget(self.label_2)
        testFrame.addWidget(QtWidgets.QLabel(
            'lena.jpg', alignment=QtCore.Qt.AlignCenter))
        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_())

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

→ Ссылка