0

I wonder if there's something I'm missing here. I used properties to modify some of my widget styles in Qt5, but it doesn't seem to work in Qt6. If it's a bug I'll report it elsewhere, but I'm just wondering if I'm doing something wrong.

I've got a simple example below, where the property change successfully triggers a style change when qt=5, but not when qt=6. The color should change as the number increments. Any help appreciated!

Qt5 working

Qt5 working

Qt6 NOT working

Qt6 NOT working

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())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Nat
  • 43
  • 6

1 Answers1

0

The behavior has slightly changed from Qt5 to 6, but in both cases the documentation already suggests 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.

This is the proper way to achieve this in Qt5 too, by the way, as it ensures that the stylesheet is properly [re]propagated to children widgets, and automatically causes repolishing anyway.

Since stylesheets are cascading, there's not an automatic way to know the origin of the style change.

In your case, this can be enough:

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

But, if you want to avoid polishing the whole application (which requires some amount of time and resources), you can temporarily set another stylesheet and restore the previous one, which is valid for widgets that might or might not have any stylesheet set:

    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)

Note:

  • singleShot is a static function, there's no need to create references for those timers, since you're not actually using them; just use QTimer.singleShot(1000, self.fun1), etc.;
  • property values for selectors should always use quotes; they work fine for single-word values, but it's good practice to always use them anyway;
musicamante
  • 41,230
  • 6
  • 33
  • 58