问题描述
请看下面的代码:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class MyScrollArea(QScrollArea):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
color_gradient = QLinearGradient(1,1,1)
color_gradient.setSpread(QGradient.PadSpread)
color_gradient.setCoordinateMode(QGradient.ObjectMode)
color_gradient.setColorAt(0,QColor('#8000D3'))
color_gradient.setColorAt(0.5,QColor('#CB5CFF'))
color_gradient.setColorAt(1,QColor('#8000D3'))
palette = self.palette()
palette.setBrush(QPalette.Window,QBrush(color_gradient))
self.setPalette(palette)
# Set widget and layout
self.scroll_widget = QWidget()
self.layout = QVBoxLayout()
self.layout.setContentsMargins(0,0)
self.layout.setSpacing(30)
self.scroll_widget.setLayout(self.layout)
self.setWidget(self.scroll_widget)
self.setWidgetResizable(True)
# Add Labels
for _ in range(40):
label = QLabel("test")
self.layout.addWidget(label)
if __name__ == '__main__':
app = QApplication([])
dialog = MyScrollArea()
dialog.show()
app.exec()
当前,设置为背景画笔的渐变随滚动条滚动。
我知道我可以将背景图像设置为 fixed with the viewport,但是我该如何修复渐变呢?
我能想到的唯一选择是将渐变放在单独的标签中并与 QScrollArea 叠加,但我希望有更简单的解决方案。
更准确地说:
我希望无论滚动条的位置如何,QScrollArea 的背景始终看起来像这样(旋转以节省空间):
也就是说,整个渐变应该始终可见,而不仅仅是它的一部分。
解决方法
这不能使用调色板来完成,因为渐变背景是在“滚动”小部件上绘制的,而您想要使其适应视口的可见部分。另外,请注意在小部件上设置调色板会自动将其设置为其子部件(由于属性继承),因此您通常应该避免这种情况,除非您确定其结果。
解决方案是覆盖滚动区域的paintEvent并为视口使用该渐变。为了确保这能正常工作,为滚动区域设置的小部件必须设置透明背景。
class MyScrollArea(QScrollArea):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# note that I've made the gradient an attribute of the instance,so it can
# be used in the paint event without recreating it everytime;
self.color_gradient = QLinearGradient(1,1,1)
self.color_gradient.setSpread(QGradient.PadSpread)
self.color_gradient.setCoordinateMode(QGradient.StretchToDeviceMode)
self.color_gradient.setColorAt(0,QColor('#8000D3'))
self.color_gradient.setColorAt(0.5,QColor('#CB5CFF'))
self.color_gradient.setColorAt(1,QColor('#8000D3'))
# ...
# set the transparent background **only** for the container widget; note
# the period before QWidget;
self.scroll_widget.setStyleSheet('.QWidget {background: transparent;}')
def paintEvent(self,event):
qp = QPainter(self.viewport())
qp.fillRect(self.viewport().rect(),self.color_gradient)