使Qt字体颜色始终与背景形成对比。 (黑或白)

时间:2019-07-25 02:22:18

标签: python pyqt

我正在为“健全性”工具定制Qt小部件,运行检查后,包含QLabel的小部件的标题颜色将更改。我当前的问题是我希望标签颜色相对于背景颜色从黑色变为白色。

我还想做些类似融合样式的事情,如果我的标题仅填充一半,则文本将为黑白以与背景形成对比。 (对于QProgressBar真的很酷)

我目前已经尝试通过测试一些CSS实例来做到这一点,但我真的不知道CSS的工作原理,而且Qt样式表中的CSS似乎有所不同。

当然,我主要尝试通过样式表执行此操作,但是我想了解如何使用QPalette进行操作。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

如果直接在窗口小部件中绘制文本(例如在QProgressBar中),则只需处理用于绘制背景的颜色。使用QPainterQPainter::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_())

由于标签是标题中的另一个小部件,因此必须找到正确的颜色。如果标签知道其父级是您的标头(并且您在progress值中具有良好的访问器),则可以重用上面的解决方案。

如果您需要通过反转颜色来在小部件上绘制标签的通用方法,则可以在图像中绘制父级渲染,反转颜色并使用它来绘制文本。

一个简单的例子作为解释:

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_())