Qt Dynamic Properties - 如果不是只有父级,是否适用于小部件?

Qt Dynamic Properties - Works for widget if not parented only?

我正在尝试在普通 QWidget 上实现按钮行为,并且正在尝试使用 setProperty() 动态更改样式表中的值。 当我使用它的 show() 方法显示小部件时它似乎运行良好,但是一旦它成为父级它就不再起作用了,我不明白发生了什么?? (不,我不想继承QPushButton,widget会有很大不同,谢谢。)

有个例子:

from PySide2 import QtCore, QtGui, QtWidgets


class Example(QtWidgets.QWidget):
    
    STYLESHEET = \
    """
    QWidget[pressed=true] 
    {
        background-color: yellow;
    }
    
    QWidget[pressed=false] 
    {
        background-color: red;
    }
    """
    
    pressed = QtCore.Signal()
    
    def __init__(self, parent=None):
        super(Example, self).__init__(parent=parent)
        
        self._buildUi()

        self.setStyleSheet(self.STYLESHEET)

        self.setProperty('pressed', False)
        
    def _buildUi(self):
        self.layout = QtWidgets.QVBoxLayout(self)
        
        self.label = QtWidgets.QLabel('toto')
        self.layout.addWidget(self.label)

    def mousePressEvent(self, e):
        self.pressed.emit()
        self.setProperty('pressed', True)
        self.setStyle(self.style())
                
        super(Example, self).mousePressEvent(e)

    def mouseReleaseEvent(self, e):
        self.setProperty('pressed', False)
        self.setStyle(self.style())
        
        super(Example, self).mouseReleaseEvent(e)
        
        
class Window(QtWidgets.QWidget):
    
    def __init__(self):
        super(Window, self).__init__()
        
        self.mainLayout = QtWidgets.QVBoxLayout(self)
                
        self.test = Example(self)
        self.mainLayout.addWidget(self.test)


if __name__ == '__main__':
    # w = Example()  # Work
    w = Window()  # Don't Work
    w.show()

如果您在 if __name__ == '__main__': 条件下切换注释行,您将能够看到同一小部件​​的两种结果。

我试过:

PS: 我 运行 此代码在 Autodesk Maya 中,因此 QApplication 实例已经存在,因为它是 Maya 本身。

你们知道发生了什么事吗?

独立小部件可以工作,因为 Qt 使用基本样式表属性(背景和边框)仅用于顶层 windows,假设顶层 window 与样式表中指定的 class 相同。

当 QWidget 有父级时,它不会自己绘制任何东西。
作为 documentation explains:

If you subclass from QWidget, you need to provide a paintEvent for your custom QWidget

因此,在 PyQt/PySide 术语中:

class Example(QtWidgets.QWidget):
    # ...
    def paintEvent(self, event):
        opt = QtWidgets.QStyleOption()
        opt.initFrom(self)
        qp = QtGui.QPainter(self)
        self.style().drawPrimitive(
            QtWidgets.QStyle.PE_Widget, opt, qp, self)