使用属性更改小部件样式表在 Qt6 中有效吗(它在 Qt5 中有效)?

Does changing widget stylesheets using properties work in Qt6 (it did in Qt5)?

我想知道我是否遗漏了什么。我在Qt5中用properties修改了我的一些widget样式,但是在Qt6中好像不行。如果它是一个错误,我会在别处报告它,但我只是想知道我是否做错了什么。

我在下面有一个简单的示例,其中 属性 更改在 qt=5 时成功触发样式更改,但在 qt=6 时则不会。颜色应该随着数字的增加而改变。感谢任何帮助!

Qt5 工作

Qt6 不工作

qt = 6

if qt == 6:
    from PyQt6.QtGui import QFont
    from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
    from PyQt6.QtCore import QTimer
elif qt == 5:
    from PyQt5.QtGui import QFont
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
    from PyQt5.QtCore import QTimer

import sys


class SampleWidget(QWidget):
    def __init__(self):
        super().__init__()

        self.timer1, self.timer2, self.timer3 = QTimer(), QTimer(), QTimer()
        self.timer1.singleShot(1000, self.fun1)
        self.timer2.singleShot(2000, self.fun2)
        self.timer3.singleShot(3000, self.close)  # noqa

        self.label = QLabel('0')
        font = QFont()
        font.setPointSize(50)
        self.label.setFont(font)
        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.setLayout(self.layout)

    def fun1(self):
        self.label.setText('1')
        self.set_property(True)

    def fun2(self):
        self.label.setText('2')
        self.set_property(False)

    def set_property(self, style_red):
        self.label.setProperty('StyleRed', style_red)
        self.label.style().unpolish(self.label)
        self.label.style().polish(self.label)
        self.label.update()
        QApplication.processEvents()


app = QApplication([])
app.setStyleSheet('QLabel[StyleRed=true]{color:red;} QLabel[StyleRed=false]{color:green;}')
gui = SampleWidget()
gui.show()
sys.exit(app.exec())

行为从 Qt5 到 6 略有变化,但在这两种情况下,文档都已经建议 the solution:

Warning: If the value of the Qt property changes after the style sheet has been set, it might be necessary to force a style sheet recomputation. One way to achieve this is to unset the style sheet and set it again.

顺便说一句,这也是在 Qt5 中实现此目的的正确方法,因为它确保样式表正确地[重新]传播到子部件,并且无论如何都会自动导致重新抛光。

由于样式表是级联的,因此没有自动了解样式更改来源的方法。

对于您的情况,这就足够了:

    def set_property(self, style_red):
        self.label.setProperty('StyleRed', style_red)
        app.setStyleSheet(app.styleSheet())

但是,如果您想避免完善 整个 应用程序(这需要一些时间和资源),您可以临时设置另一个样式表并恢复之前的样式表,这对可能有也可能没有任何样式表集的小部件有效:

    def set_property(self, style_red):
        self.label.setProperty('StyleRed', style_red)
        old = self.label.styleSheet()
        if not old:
            self.label.setStyleSheet('* {}')
        self.label.setStyleSheet(old)

注:

  • singleShot 是一个静态函数,没有必要为这些计时器创建引用,因为您实际上并没有使用它们;只需使用 QTimer.singleShot(1000, self.fun1),等等;
  • 属性 选择器的值应始终使用引号;它们适用于单个单词值,但无论如何始终使用它们是一种很好的做法;