【问题标题】:Make Qt Font color always contrast with background. (black or white)使 Qt 字体颜色始终与背景形成对比。 (黑或白)
【发布时间】:2019-07-25 19:16:35
【问题描述】:

我正在为“健全”工具开发自定义 Qt 小部件,运行检查后,包含 QLabel 的小部件的标题颜色将发生变化。我目前的问题是我想让标签颜色相对于背景颜色从黑色变为白色。

我还想做的是类似融合风格的提议,如果我的标题只填了一半,那么文本将是黑白的,以与背景形成对比。 (对于 QProgressBar 来说真的很酷)

我目前尝试通过使用一些 CSS 示例进行测试来做到这一点,但我真的不知道 CSS 是如何工作的,而且它似乎与 Qt 样式表不同。

当然,我主要尝试通过样式表来做到这一点,但我想了解如何使用 QPalette 来做到这一点。

感谢您的帮助。

【问题讨论】:

  • 你能解释一下吗?也许一张图片或 gif 可以帮助你更好地了解自己
  • ddgobkiprc33d.cloudfront.net/… 我的主要目标之一是只拥有一个 QLabel 的子类并且可以从其父背景自动调整其颜色的小部件。 (为了计算我发现这个:nbdtech.com/Blog/archive/2008/04/27/…)如果父颜色亮度太高,文本将是黑色,如果亮度低,颜色将是黑色。如果背景颜色不纯色,我还希望能够将标签绘制成半黑/白。
  • 你是什么意思父颜色?你是说背景颜色吗?
  • 是的父背景颜色,抱歉疏忽。

标签: python pyqt


【解决方案1】:

如果您的文本直接在小部件中绘制(例如在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_())

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

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

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

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

【讨论】:

  • 感谢 Romha 的帮助,但从我尝试过的例子来看,你填充了背景?我想做的是拥有一个通用的 QLabel,我可以将其作为自定义 QProgressBar 或 QWidget 的父级,并且谁将从后面的颜色(父背景颜色)中调整其颜色。我将使用paintEvent进行更多测试,实际上我只尝试过样式表和QPalette。
  • 在我的第二个示例中,我创建了一个虚拟小部件window,它可以像进度条一样更改其背景,还创建了一个标签ContrastedLabel,它将文本颜色与其父渲染相匹配。实际上,您可以在大多数小部件中使用ContrastedLabel
猜你喜欢
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 2011-04-25
  • 2015-06-11
  • 1970-01-01
  • 2020-01-19
相关资源
最近更新 更多