如果您的文本直接在小部件中绘制(例如在QProgressBar 中),您只需处理用于绘制背景的颜色。使用QPainter 和QPainter::setClipPath 方法非常简单:
class ProgressBar(QLabel):
def __init__(self):
super().__init__()
self.progression = 0
self.startTimer(200)
def paintEvent(self, event):
text = "This is a text"
super().paintEvent(event)
painter = QPainter(self)
self.setFont(QFont("Helvetica", 24))
boundingRect = QRect(0, 0, self.width(), self.height())
progressionRect = boundingRect.adjusted(0, 0, - self.width() * (1 - self.progression), 0)
leftRect = boundingRect.adjusted(progressionRect.width(), 0, 0, 0)
painter.setBrush(Qt.black)
painter.drawRect(progressionRect)
painter.setClipRect(leftRect)
painter.drawText(boundingRect, Qt.AlignCenter,text)
painter.setPen(Qt.white)
painter.setClipRect(progressionRect)
painter.drawText(boundingRect, Qt.AlignCenter, text)
def timerEvent(self, event):
self.progression = min(1.0, self.progression + 0.02)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
p = ProgressBar()
p.resize(640, 480)
p.show()
sys.exit(app.exec_())
由于您的标签是标题中的另一个小部件,因此您必须找到正确的颜色。如果标签知道其父级是您的标头(并且您在进度值中有良好的访问器),您可以重用上面的解决方案。
如果您需要一种通过反转颜色在小部件上绘制标签的通用方法,您可以在图像中绘制父级渲染,反转颜色并使用它来绘制文本。
一个简单的例子作为解释:
class Window(QLabel):
def __init__(self):
super().__init__()
self.progression = 0
self.startTimer(200)
def paintEvent(self, event):
super().paintEvent(event)
painter = QPainter(self)
boundingRect = QRect(0, 0, self.width(), self.height() * self.progression)
painter.setBrush(Qt.black)
painter.drawRect(boundingRect)
def timerEvent(self, event):
self.progression = min(1.0, self.progression + 0.02)
self.update()
class ContrastedText(QFrame):
def __init__(self, text="", parent=None):
super().__init__(parent)
self.text = text
def paintEvent(self, event):
super().paintEvent(event)
painter = QPainter(self)
self.setFont(QFont("Helvetica", 24))
boundingRect = QRect(0, 0, self.width(), self.height())
fm = QFontMetrics(painter.font())
textBoundingRect = fm.boundingRect(boundingRect, Qt.AlignCenter, self.text)
# No parent. The text is black
if not self.parent():
painter.drawText(boundingRect, Qt.AlignCenter, self.text)
return
# Get the parents render and invert its color to have the good constrast
render = QPixmap(self.parent().size()).toImage()
self.parent().render(render, QPoint(), QRegion(), QWidget.DrawWindowBackground)
render.invertPixels(QImage.InvertRgba)
# Define a clip path containing the text and draw the image
path = QPainterPath()
path.addText(textBoundingRect.topLeft(), painter.font(), self.text)
painter.setClipPath(path)
painter.drawImage(-self.mapTo(self.parent(), QPoint(0, 0)), render)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
layout = QVBoxLayout(window)
label = ContrastedText("This is a text")
layout.addWidget(label)
window.resize(640, 480)
window.show()
sys.exit(app.exec_())