Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QWidget::setStyleSheet() breaks cascade inheritance
QtWS25 Last Chance

QWidget::setStyleSheet() breaks cascade inheritance

Scheduled Pinned Locked Moved Unsolved General and Desktop
24 Posts 5 Posters 5.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • kshegunovK kshegunov

    I'm sad to be the hand that puts the stick in your wheel, but I believe this is a "feature" ... one that I also believe doesn't have a (reasonable) workaround. As far as my frail memory serves me, from the point where you set a stylesheet to the widget there's no more inheritance*. To have the correct style one has to set the whole stylesheet anew.
    As for why space differs, I'd hazard a guess that QString(" ").isEmpty() is simply false, while if it were true the setStyleSheet() method just quickly returns doing nothing and/or simply clears the current stylesheet (thus allowing the parent one to be used).

    * Because I believe there's no inheritance as such. If there's a stylesheet set it is used as such, if not then it searches if the parent has a stylesheet, no mixing, matching and inheriting style as you'd be used to from CSS.

    JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by
    #6

    @kshegunov
    As per @SGaist this sort of thing is not the issue. Please, it has nothing to do with spaces.

    It only happens on one kind of node. There is a problem here.

    kshegunovK 1 Reply Last reply
    0
    • JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by JonB
      #7

      All of you have picked up on the space. It has nothing to do with that. Please.

      Just pretend I had written anything you like as legal QSS. Let's say child.setStyleSheet("QPushButton {} "). OK now?

      I did say at the outset:

      However, if I test child.setStyleSheet(" ") (i.e. anything, just a single space will do) it

      Anything. Just not an empty string.

      I know how inheritance works. I know it works in all situations than my problem one.

      Christian EhrlicherC 1 Reply Last reply
      0
      • JonBJ JonB

        @kshegunov
        As per @SGaist this sort of thing is not the issue. Please, it has nothing to do with spaces.

        It only happens on one kind of node. There is a problem here.

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by
        #8

        @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

        It only happens on one kind of node. There is a problem here.

        Then, if I'm wrong that is, I have no bloody clue.

        Read and abide by the Qt Code of Conduct

        1 Reply Last reply
        0
        • JonBJ JonB

          All of you have picked up on the space. It has nothing to do with that. Please.

          Just pretend I had written anything you like as legal QSS. Let's say child.setStyleSheet("QPushButton {} "). OK now?

          I did say at the outset:

          However, if I test child.setStyleSheet(" ") (i.e. anything, just a single space will do) it

          Anything. Just not an empty string.

          I know how inheritance works. I know it works in all situations than my problem one.

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #9

          @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

          It has nothing to do with that

          Then take a look at QWidget::setStyleSheet(): https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qwidget.cpp.html#_ZN7QWidget13setStyleSheetERK7QString (line 2728)

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          kshegunovK 1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

            It has nothing to do with that

            Then take a look at QWidget::setStyleSheet(): https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qwidget.cpp.html#_ZN7QWidget13setStyleSheetERK7QString (line 2728)

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by
            #10

            @Christian-Ehrlicher said in QWidget::setStyleSheet() breaks cascade inheritance:

            Then take a look at QWidget::setStyleSheet()

            Oh god, that's some mess ... but on the bright side it does seem to support my original hypothesis ...

            Read and abide by the Qt Code of Conduct

            1 Reply Last reply
            0
            • JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #11

              @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:
              What hypothesis ?

              1 Reply Last reply
              0
              • kshegunovK kshegunov

                I'm sad to be the hand that puts the stick in your wheel, but I believe this is a "feature" ... one that I also believe doesn't have a (reasonable) workaround. As far as my frail memory serves me, from the point where you set a stylesheet to the widget there's no more inheritance*. To have the correct style one has to set the whole stylesheet anew.
                As for why space differs, I'd hazard a guess that QString(" ").isEmpty() is simply false, while if it were true the setStyleSheet() method just quickly returns doing nothing and/or simply clears the current stylesheet (thus allowing the parent one to be used).

                * Because I believe there's no inheritance as such. If there's a stylesheet set it is used as such, if not then it searches if the parent has a stylesheet, no mixing, matching and inheriting style as you'd be used to from CSS.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #12

                @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:

                I'm sad to be the hand that puts the stick in your wheel, but I believe this is a "feature" ... one that I also believe doesn't have a (reasonable) workaround. As far as my frail memory serves me, from the point where you set a stylesheet to the widget there's no more inheritance*. To have the correct style one has to set the whole stylesheet anew.
                [nonsense about the space]
                * Because I believe there's no inheritance as such. If there's a stylesheet set it is used as such, if not then it searches if the parent has a stylesheet, no mixing, matching and inheriting style as you'd be used to from CSS.

                Basically if you set a border style to the parent, but then set only background for the child, the parent's style is completely disregarded from the child's painting onward.

                Read and abide by the Qt Code of Conduct

                JonBJ 1 Reply Last reply
                0
                • kshegunovK kshegunov

                  @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:

                  I'm sad to be the hand that puts the stick in your wheel, but I believe this is a "feature" ... one that I also believe doesn't have a (reasonable) workaround. As far as my frail memory serves me, from the point where you set a stylesheet to the widget there's no more inheritance*. To have the correct style one has to set the whole stylesheet anew.
                  [nonsense about the space]
                  * Because I believe there's no inheritance as such. If there's a stylesheet set it is used as such, if not then it searches if the parent has a stylesheet, no mixing, matching and inheriting style as you'd be used to from CSS.

                  Basically if you set a border style to the parent, but then set only background for the child, the parent's style is completely disregarded from the child's painting onward.

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by
                  #13

                  @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:

                  where you set a stylesheet to the widget there's no more inheritance*

                  But that's wrong. There is inheritance. It works all over the place. QSS behaves similarly to CSS.

                  kshegunovK 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:

                    where you set a stylesheet to the widget there's no more inheritance*

                    But that's wrong. There is inheritance. It works all over the place. QSS behaves similarly to CSS.

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #14

                    @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                    But that's wrong. There is inheritance. It works all over the place. QSS behaves similarly to CSS.

                    Not according to my quick glance through the source.

                    Read and abide by the Qt Code of Conduct

                    JonBJ 1 Reply Last reply
                    0
                    • kshegunovK kshegunov

                      @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                      But that's wrong. There is inheritance. It works all over the place. QSS behaves similarly to CSS.

                      Not according to my quick glance through the source.

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #15

                      @kshegunov
                      Hmmmmm.

                      Look, at this point, let me look again next week and make absolutely certain. I claim I am finding that inheritance works like it does in CSS, That's what "cascading" is about. I can set one style on a high node and a different style on a low node and they both appear. At this point let me check up and decide whether I am correct or I am going insane. :)

                      EDIT
                      https://doc.qt.io/qt-5/stylesheet-syntax.html#cascading

                      Cascading

                      Style sheets can be set on the QApplication, on parent widgets, and on child widgets. An arbitrary widget's effective style sheet is obtained by merging the style sheets set on the widget's ancestors (parent, grandparent, etc.), as well as any style sheet set on the QApplication.

                      Is that not in direct contradiction to your

                      Basically if you set a border style to the parent, but then set only background for the child, the parent's style is completely disregarded from the child's painting onward.

                      ?

                      If you couldn't do this, whenever you set a stylesheet on some widget it would lose all your application- or window-wide styles you have set. It's fundamental to CSS/QSS. I don't know why people are saying stylesheets on different nodes don't merge.

                      kshegunovK 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @kshegunov
                        Hmmmmm.

                        Look, at this point, let me look again next week and make absolutely certain. I claim I am finding that inheritance works like it does in CSS, That's what "cascading" is about. I can set one style on a high node and a different style on a low node and they both appear. At this point let me check up and decide whether I am correct or I am going insane. :)

                        EDIT
                        https://doc.qt.io/qt-5/stylesheet-syntax.html#cascading

                        Cascading

                        Style sheets can be set on the QApplication, on parent widgets, and on child widgets. An arbitrary widget's effective style sheet is obtained by merging the style sheets set on the widget's ancestors (parent, grandparent, etc.), as well as any style sheet set on the QApplication.

                        Is that not in direct contradiction to your

                        Basically if you set a border style to the parent, but then set only background for the child, the parent's style is completely disregarded from the child's painting onward.

                        ?

                        If you couldn't do this, whenever you set a stylesheet on some widget it would lose all your application- or window-wide styles you have set. It's fundamental to CSS/QSS. I don't know why people are saying stylesheets on different nodes don't merge.

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by kshegunov
                        #16

                        @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                        Is that not in direct contradiction to your

                        Yes, I checked, I'm wrong. Here's the test case:

                        #include <QApplication>
                        #include <QWidget>
                        #include <QLabel>
                        #include <QVBoxLayout>
                        
                        int main(int argc, char ** argv)
                        {
                            QApplication app(argc, argv);
                            Q_UNUSED(app);
                        
                            QWidget main;
                            main.setGeometry(0, 0, 100, 50);
                            main.setStyleSheet("QWidget { color: blue }");
                            main.setLayout(new QVBoxLayout());
                        
                            QLabel * child = new QLabel(&main);
                            child->setText("Some text");
                            child->setStyleSheet("QLabel { background-color: gray }");
                            main.layout()->addWidget(child);
                        
                            main.show();
                        
                            return QApplication::exec();
                        }
                        

                        Read and abide by the Qt Code of Conduct

                        JonBJ 1 Reply Last reply
                        0
                        • kshegunovK kshegunov

                          @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                          Is that not in direct contradiction to your

                          Yes, I checked, I'm wrong. Here's the test case:

                          #include <QApplication>
                          #include <QWidget>
                          #include <QLabel>
                          #include <QVBoxLayout>
                          
                          int main(int argc, char ** argv)
                          {
                              QApplication app(argc, argv);
                              Q_UNUSED(app);
                          
                              QWidget main;
                              main.setGeometry(0, 0, 100, 50);
                              main.setStyleSheet("QWidget { color: blue }");
                              main.setLayout(new QVBoxLayout());
                          
                              QLabel * child = new QLabel(&main);
                              child->setText("Some text");
                              child->setStyleSheet("QLabel { background-color: gray }");
                              main.layout()->addWidget(child);
                          
                              main.show();
                          
                              return QApplication::exec();
                          }
                          
                          JonBJ Online
                          JonBJ Online
                          JonB
                          wrote on last edited by JonB
                          #17

                          @kshegunov
                          Phew! :)

                          The whole point of this question is that usually everything does merge, always has done. I am presently stuck in one situation in a complex design where if a node has *any kind of styleSheet set on it something then says that should terminate all previous styles. It should not. The question is why? :)

                          From your example, imagine that after

                          child->setStyleSheet("QLabel { background-color: gray }");
                          

                          from then on all childs descendants do not now respect the main.setStyleSheet("QWidget { color: blue }"); from earlier on. (But do still respect child's QLabel { background-color: gray }.)

                          The behaviour, I think, will not lie in setStyleSheet(). Rather, it will be in the code which calculates the cascaded/inherited styles during rendering.

                          kshegunovK 1 Reply Last reply
                          0
                          • JonBJ JonB

                            @kshegunov
                            Phew! :)

                            The whole point of this question is that usually everything does merge, always has done. I am presently stuck in one situation in a complex design where if a node has *any kind of styleSheet set on it something then says that should terminate all previous styles. It should not. The question is why? :)

                            From your example, imagine that after

                            child->setStyleSheet("QLabel { background-color: gray }");
                            

                            from then on all childs descendants do not now respect the main.setStyleSheet("QWidget { color: blue }"); from earlier on. (But do still respect child's QLabel { background-color: gray }.)

                            The behaviour, I think, will not lie in setStyleSheet(). Rather, it will be in the code which calculates the cascaded/inherited styles during rendering.

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by
                            #18

                            @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                            The question is why?

                            Not the faintest idea. I know it's not too helpful, but the debugger is your friend here ...
                            (you may want to try GammaRay as well)

                            Read and abide by the Qt Code of Conduct

                            JonBJ 1 Reply Last reply
                            0
                            • kshegunovK kshegunov

                              @JonB said in QWidget::setStyleSheet() breaks cascade inheritance:

                              The question is why?

                              Not the faintest idea. I know it's not too helpful, but the debugger is your friend here ...
                              (you may want to try GammaRay as well)

                              JonBJ Online
                              JonBJ Online
                              JonB
                              wrote on last edited by
                              #19

                              @kshegunov said in QWidget::setStyleSheet() breaks cascade inheritance:

                              but the debugger is your friend here

                              Not when one is writing from Python, so you can't step through Qt stuff....

                              1 Reply Last reply
                              0
                              • JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by JonB
                                #20

                                I will spend another day next week trying to reproduce on a test example :) [I may have already found one odd case with QTabWidget.] Will report back.

                                1 Reply Last reply
                                2
                                • JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by JonB
                                  #21

                                  I just wanted to report back in case anybody thinks I am slacking....

                                  Spent another day of frustration :( In my real-life, I have something like hierarchy ... > QTabWidget > QScrollArea > .... Higher up sets stylesheet like QScrollBar { ... }. I am finding that setting any kind of non-empty [including nothing related to scrolls/tabs] setStyleSheet { ... } on either the QScrollArea or on its direct parent (like QTabWidget here) stops inheritance of the scrollbars. Putting in setStyleSheet { ... } anywhere else (e.g. higher up than direct parent) does not stop inheritance....

                                  ...But of course, try as I might, I cannot reproduce this behaviour on any kind of standalone... :( It's proving impossible to recognise what the difference is.

                                  One thing: I just happenstanced across @sierdzio's comment from Feb 2019 at https://forum.qt.io/topic/100083/qt-how-to-prevent-child-qdialogs-or-qwidgets-from-inheriting-parent-stylesheet/2:

                                  If you want to stop subwidgets from inheriting the style, call setStyleSheet("") on widgets which should have default style sheet.

                                  [Leave aside for the moment that I find setStyleSheet("") has no effect/does not cancel inheritance, it must be setStyleSheet(<something-here>), even if it's just " ".]

                                  Is @sierdzio around? I need him or somebody to give me an actual reference to where they have seen this in the docs, please? It does not seem to me things work like that, at least not in the cases I have tried (and see @kshegunov's sample code above), but there does seem to be a possible relationship between this statement and (some of) my issue, so I really need to pursue....

                                  1 Reply Last reply
                                  0
                                  • sierdzioS Offline
                                    sierdzioS Offline
                                    sierdzio
                                    Moderators
                                    wrote on last edited by
                                    #22

                                    Heh, yes I am around. I didn't respond earlier because I thought I had an answer... then rechecked the docs and it turned out I remembered it incorrectly.

                                    So, I don't have an explanation for you. Perhaps it is a Qt bug (quite probably it is, in fact!), or you are doing something wrong (seems unlikely, from what you describe). I can only offer some hints that might help:

                                    • do you break parent/child relationship on your widgets at any point (using QObject::setParent() or something similar)? It could break QSS inheritance chain, too
                                    • I have recently stumbled upon some widgets which do not work with QSS at all if they have custom QPalette set. I don't have a full list, from memory I'd say it was at least QLabel and QLineEdit, probably more. So if you do call setPalette() anywhere - this could be your problem
                                    • there is a way to avoid setting custom stylesheets for particular widgets. If you want some widget (let's call it WidgetA) to have different look, but you also want to have only one application-wide QSS file, then: pick some property name and set it WidgetA->setProperty("myCustomName", true);, then in your QSS file, you can create special rules only for widget(s) which have this property: QWidget[myCustomName] { background-color: #FFFFFF; border: 1px solid #E9EDEF;}. It works, and as a bonus you get all your style code in a single, global place :-)

                                    (Z(:^

                                    JonBJ 1 Reply Last reply
                                    0
                                    • sierdzioS sierdzio

                                      Heh, yes I am around. I didn't respond earlier because I thought I had an answer... then rechecked the docs and it turned out I remembered it incorrectly.

                                      So, I don't have an explanation for you. Perhaps it is a Qt bug (quite probably it is, in fact!), or you are doing something wrong (seems unlikely, from what you describe). I can only offer some hints that might help:

                                      • do you break parent/child relationship on your widgets at any point (using QObject::setParent() or something similar)? It could break QSS inheritance chain, too
                                      • I have recently stumbled upon some widgets which do not work with QSS at all if they have custom QPalette set. I don't have a full list, from memory I'd say it was at least QLabel and QLineEdit, probably more. So if you do call setPalette() anywhere - this could be your problem
                                      • there is a way to avoid setting custom stylesheets for particular widgets. If you want some widget (let's call it WidgetA) to have different look, but you also want to have only one application-wide QSS file, then: pick some property name and set it WidgetA->setProperty("myCustomName", true);, then in your QSS file, you can create special rules only for widget(s) which have this property: QWidget[myCustomName] { background-color: #FFFFFF; border: 1px solid #E9EDEF;}. It works, and as a bonus you get all your style code in a single, global place :-)
                                      JonBJ Online
                                      JonBJ Online
                                      JonB
                                      wrote on last edited by JonB
                                      #23

                                      @sierdzio
                                      Hi there, thanks for replying :)

                                      • No reparenting, nothing going on in code like that (bit I will recheck tomorrow). The layout is designed from Creator, not manipulated in our code.
                                      • Nothing like palettes or special widgets.
                                      • Yep, I did dynamic properties in my previous project. Not at issue here. I have done a lot of CSS for my sinds, so I do know what it's all about.

                                      So can we be clear, please? Are you withdrawing your:

                                      If you want to stop subwidgets from inheriting the style, call setStyleSheet("") on widgets which should have default style sheet.

                                      I have not seen Qt says it would do that. Unless it says it does I would not expect it to --- it would break the simplest case of defining a global set of styles and then occasionally doing one thing on an element if that cancelled all inheritance. My "standalone" tests do not reveal such behaviour.

                                      Yet my problem cases are behaving as though that does happen, in unrepeatable circumstances. That is why I ask. Something seems to be going "if such and such an element has any stylesheet of is own, cancel inheritance from its ancestors at this point and down to descendants". When it should not.

                                      As I have said elsewhere, it may have something to do with QTabWidgets & QScrollBars. I have already discovered that "containers" like these do not behave as one would expect for inheritance, I may make a separate post tomorrow showing that. EDIT See https://forum.qt.io/topic/111137/stylesheet-inheritance-and-container-widgets.

                                      1 Reply Last reply
                                      0
                                      • JonBJ Online
                                        JonBJ Online
                                        JonB
                                        wrote on last edited by
                                        #24

                                        I have raised https://bugreports.qt.io/browse/QTBUG-81958 against related https://forum.qt.io/topic/111137/stylesheet-inheritance-and-container-widgets, as I'm not getting an answer here.

                                        1 Reply Last reply
                                        0

                                        • Login

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • Users
                                        • Groups
                                        • Search
                                        • Get Qt Extensions
                                        • Unsolved