可滚动小部件的 QPaintEvent 事件矩形

QPaintEvent event rect for scrollable widget

我有一个 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()

QPaintEvent::rect() returns 可见矩形,而不是小部件本身的矩形,因此您观察到此行为。解决方案是:

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