Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-81958

Stylesheet inheritance and "container" widgets

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.12.2
    • Widgets: Style Sheets
    • None
    • All

    Description

      Tested by me under Qt 5.12.2 shipped with Ubuntu 19.04, but believed to apply to all versions/platforms.

      I am finding there is strange and quite undocumented behaviour on "container" widgets and stylesheets.  Briefly, stylesheets on individual widget elements in a hierarchy should "inherit"/"cascade" downward to descendants. But I am finding strange behaviour with a stylesheet set on "container" widgets (i.e. those Qt Designer groups as Containers).

      Start from

      import sys
      from PySide2 import QtWidgets
      # from PyQt5 import QtWidgets

      def window():
        app = QtWidgets.QApplication(sys.argv)

        # mw: main window
        mw = QtWidgets.QMainWindow()
        mw.setGeometry(100,100,200,250)
        mw.setWindowTitle("PySide2")

        # sw: tab widget, set as main window's central widget
        tw = QtWidgets.QTabWidget(mw)
        mw.setCentralWidget(tw)

        # p1: page #1 of tab widget, it is a scroll area
        p1 = QtWidgets.QScrollArea(tw)
        p1.setFixedHeight(100)
        tw.addTab(p1, "Page 1")

        # wg: widget on page, tall enough to cause scroll area scrollbars
        wg = QtWidgets.QWidget(p1)
        wg.setFixedHeight(200)
        p1.setWidget(wg)

        # main window sets color to red
        mw.setStyleSheet("* { background-color: red; }")
        # tab widget sets color to blue
        # affects the tab widget itself, but it has no effect on any page inside the tab widget
        # tw.setStyleSheet("* { background-color: blue; }")

        mw.show()
        sys.exit(app.exec_())

        if _name_ == '_main_':
          window()

      This creates a simple hierarchy: QMainWindow > QTabWidget > QScrollArea > QWidget. When run the above code produces:

      1.

      Good! The red is set on QMainWindow and inherits down to QTabWidget and on into its QScrollArea and content.

      Now let's uncomment the line which sets a stylesheet on the QTabWidget:

      tw.setStyleSheet("* { background-color: blue; }")

      2.

      Now what's going on here? The QTabWidget itself is blue, but the QScrollArea remains red? It's as though the QTabWidget "partially stands outside" the inheritance hierarchy: it inherits from its parent, but its own setting does not cascade down to its children, they inherit from higher up the tree....? It's as though we have two separate hierarchies:

      QMainWindow > QTabWidget > [STOP]
      QMainWindow > QScrollArea > QWidget

      I have also tested the above with a QStackedWidget instead of QTabWidget "container", and behaviour is the same.

      How does this work? Where is there any mention when this applies to what widgets in the docs?
       

      Continuing from above code. Let's make the two style lines as follows:

      mw.setStyleSheet("* { background-color: red; } QScrollBar { background-color: yellow; }")
      tw.setStyleSheet("* { background-color: blue; } QScrollBar { background-color: green; }")

       

      3.

      Again, this shows the scrollbar color is inherited from QMainWindow and ignored from QTabWidget, as before. Now let's comment out the QMainWindow's stylesheet totally:

      # mw.setStyleSheet("* { background-color: red; } QScrollBar { background-color: yellow; }")
      tw.setStyleSheet("* { background-color: blue; } QScrollBar { background-color: green; }")

       

      4.

      Hmm, now descendants are all blue & green, which comes from QTabWidget, which we said does not cascade to children....

      So, what we are seeing now seems to be:

      • When all we do is set style on QTabWidget it does cascade down to children...
      • ...but if something higher up the hierarchy (QMainWindow here, but I've tried others) happens to have a stylesheet then inheritance is taken from there and QTabWidget is ignored.

       

      Finally, here's really scary behaviour:

      mw.setStyleSheet("QPushButton { border: none; }")
      tw.setStyleSheet("* { background-color: blue; } QScrollBar { background-color: green; }")

      5.

      I have put a stylesheet on QMainWindow but with a rule totally unrelated to the widgets I am showing. [I could have put anything non-empty, even \\\{{mw.setStyleSheet(" ")}}.] Nothing now inherits from QTabWidget.

      Now let's change to

        # or omit the following line completely
        mw.setStyleSheet("")

       

      6.

      With no/empty stylesheet on QMainWindow, and only in this case, the background and QScrollBar do take from QTabWidget.

      Final Note

      My examples use colours because it's easiest to illustrate.  As per https://doc.qt.io/Qt-5/stylesheet-syntax.html#inheritance I have tried

      QCoreApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)

      This makes no difference to the results in pictures #1 to #5.  Only in #6 does it make a difference, and even then it changes the background color but still cancels the scrollbar colour inheritance.  I do not believe that is the issue.

      Pictures #5 & #6 require special investigation.  They illustrate some "special case" when having any kind of stylesheet string at all on an element (container?) interferes with/cancels all subsequent inheritance, when  it should not.  I am having other problems related to this behaviour in hierarchies too complex to break down so I could report here, which is the ultimate root of this issue.

      This issue originally raised by me at https://forum.qt.io/topic/111137/stylesheet-inheritance-and-container-widgets, and also my related https://forum.qt.io/topic/110974/qwidget-setstylesheet-breaks-cascade-inheritance where I am attempting to find the underlying cause of pictures #5 & #6 which is interfering with a real-life complex hierarchy.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            jonbrave J Barchan
            Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes