Прямое событие QPaintEvent для прокручиваемого виджета

#python #pyside2

Вопрос:

У меня есть переопределение QPaintEvent для пользовательского виджета с фиксированным размером. Этот фиксированный размер может изменяться для каждого экземпляра, но в этом простом примере я установил его. однако paintEvent не учитывает это, поэтому, когда пользователи прокручивают вправо, прямоугольник не должен закруглять углы, так как виджет выходит за пределы видимого окна просмотра. Как мне это исправить?

Полный виджет нарисован правильно…

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

Когда я изменяю размер диалогового окна и прокручиваю вправо, вы увидите, что слева появляются закругленные углы… когда этого НЕ должно быть.

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

Они должны выглядеть вот так…

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

Код

 import os
import sys
from PySide2 import  QtGui, QtWidgets, QtCore, QtSvg


class Card(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(Card, self).__init__(parent=parent)

        self.label = QtWidgets.QLabel('Help This Paint Event Is Broken')
        self.label.setFixedHeight(40)
        self.label.setFixedWidth(300)

        self.mainLayout = QtWidgets.QVBoxLayout(self)
        self.mainLayout.addWidget(self.label)

    # overrides
    def paintEvent(self, event):
        painter = QtGui.QPainter() 
        painter.begin(self) 
        painter.setOpacity(1.0)
        painter.setRenderHints(QtGui.QPainter.Antialiasing)
        painter.setPen(QtGui.QColor(0, 0, 0, 128))
        painter.setPen(QtCore.Qt.NoPen)
        painter.setBrush(QtGui.QColor('#F44336'))
        painter.drawRoundedRect(event.rect(), 12, 12)
        painter.setRenderHint(QtGui.QPainter.Antialiasing) 
        painter.end() 


class ListViewExample(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ListViewExample, self).__init__(parent)
        self.resize(200,200)

        self.listView = QtWidgets.QListWidget()
        self.listView.setSpacing(10)
        self.listView.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
        self.listView.verticalScrollBar().setSingleStep(10)

        # layout
        self.mainLayout = QtWidgets.QVBoxLayout()
        self.mainLayout.setContentsMargins(0,0,0,0)
        self.mainLayout.addWidget(self.listView)
        self.setLayout(self.mainLayout)

        for x in range(50):
            wgt = Card()
            self.appendItem(wgt)

    def appendItem(self, widget):
        lwi = QtWidgets.QListWidgetItem()
        lwi.setSizeHint(widget.sizeHint())
        self.listView.addItem(lwi)
        self.listView.setItemWidget(lwi, widget) 


################################################################################
# Widgets
################################################################################
def unitTest_CardDelegate():
    app = QtWidgets.QApplication(sys.argv)
    window = ListViewExample()
    window.show()
    app.exec_()


if __name__ == '__main__':
    pass
    unitTest_CardDelegate()
 

Ответ №1:

QPaintEvent::rect() возвращает видимый прямоугольник, а не прямоугольник самого виджета, поэтому вы наблюдаете это поведение. Решение заключается в следующем:

 painter.drawRoundedRect(self.rect(), 12, 12)