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
Forum Updated to NodeBB v4.3 + New Features

QWidget::setStyleSheet() breaks cascade inheritance

Scheduled Pinned Locked Moved Unsolved General and Desktop
24 Posts 5 Posters 5.5k Views 4 Watching
  • 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.
  • J Offline
    J Offline
    JonB
    wrote on 24 Jan 2020, 11:54 last edited by JonB
    #1

    I am stuck on inexplicable behaviour as a result of a QWidget::setStyleSheet().

    1. I have a parent hierarchy which includes ancestor.setStyleSheet(something). Let's say it's {background-color: red;}.
    2. I add child to parent.
    3. At this point all is well: child and its descendants correctly inherit the ancestor's red color.
    4. If I test child.setStyleSheet("") (i.e. empty string), all is well, nothing changes.
    5. However, if I test child.setStyleSheet(" ") (i.e. anything, just a single space will do) it breaks the cascade inheritance: child and its descendants are no longer red!

    I am aware this sounds bizarre, but it's deffo happening from just that change.

    [The reason this is a problem, as I'm sure you'll ask, is: Qt Designer is used to produce the widgets. There every widget has a styleSheet property, which goes into the .ui file and produces a setStyleSheet() statement. If you don't visit the property it doesn't output any statemant and all is well. But if you happen to click into it you get a whitespace-only setStyleSheet() statement, and that's enough to break the run-time behaviour, even though you don't even know you have set a stylesheet.]

    Of course I have tried to knock up a small example, but that doesn't exhibit this behaviour. The real hierarchy is large, and uses various widget types, and I don't know which bits of it cause this. [Note: I have searched, there is no code which manipulates any of the stylesheets after the generated construction code in setupUI().] If it is relevant it may be that I see this when QTabWidget, QScrollArea & QScrollBar are involved, though my tests with that still did not produce the problem.

    Because I cannot produce a test, I'm desperately looking for any clue as to why child.setStyleSheet(" ") could possibly cause this where child.setStyleSheet("") does not??!! Presumably something, somewhere in Qt widget stuff is saying "if an element has no/only empty styleSheet allow cascade inheritance to proceed, but if it is not empty (even just a space) cancel all inheritance". According to me this behaviour should simply never happen? GULP :(

    K 1 Reply Last reply 24 Jan 2020, 20:22
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 24 Jan 2020, 20:14 last edited by
      #2

      Hi,

      I don't have the exact answer but an empty string or a string with one space is pretty different when parsing.

      I would guess that the space introduces an invalid style sheet.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      J 1 Reply Last reply 24 Jan 2020, 20:16
      0
      • S SGaist
        24 Jan 2020, 20:14

        Hi,

        I don't have the exact answer but an empty string or a string with one space is pretty different when parsing.

        I would guess that the space introduces an invalid style sheet.

        J Offline
        J Offline
        JonB
        wrote on 24 Jan 2020, 20:16 last edited by JonB
        #3

        @SGaist
        Thanks, but it's not that. I mean if I have anything at all, yes including something perfectly correct for QSS, it stops inheritance from there downward, The space was only a minimal illustration!

        1 Reply Last reply
        0
        • J JonB
          24 Jan 2020, 11:54

          I am stuck on inexplicable behaviour as a result of a QWidget::setStyleSheet().

          1. I have a parent hierarchy which includes ancestor.setStyleSheet(something). Let's say it's {background-color: red;}.
          2. I add child to parent.
          3. At this point all is well: child and its descendants correctly inherit the ancestor's red color.
          4. If I test child.setStyleSheet("") (i.e. empty string), all is well, nothing changes.
          5. However, if I test child.setStyleSheet(" ") (i.e. anything, just a single space will do) it breaks the cascade inheritance: child and its descendants are no longer red!

          I am aware this sounds bizarre, but it's deffo happening from just that change.

          [The reason this is a problem, as I'm sure you'll ask, is: Qt Designer is used to produce the widgets. There every widget has a styleSheet property, which goes into the .ui file and produces a setStyleSheet() statement. If you don't visit the property it doesn't output any statemant and all is well. But if you happen to click into it you get a whitespace-only setStyleSheet() statement, and that's enough to break the run-time behaviour, even though you don't even know you have set a stylesheet.]

          Of course I have tried to knock up a small example, but that doesn't exhibit this behaviour. The real hierarchy is large, and uses various widget types, and I don't know which bits of it cause this. [Note: I have searched, there is no code which manipulates any of the stylesheets after the generated construction code in setupUI().] If it is relevant it may be that I see this when QTabWidget, QScrollArea & QScrollBar are involved, though my tests with that still did not produce the problem.

          Because I cannot produce a test, I'm desperately looking for any clue as to why child.setStyleSheet(" ") could possibly cause this where child.setStyleSheet("") does not??!! Presumably something, somewhere in Qt widget stuff is saying "if an element has no/only empty styleSheet allow cascade inheritance to proceed, but if it is not empty (even just a space) cancel all inheritance". According to me this behaviour should simply never happen? GULP :(

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 24 Jan 2020, 20:22 last edited by kshegunov
          #4

          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.

          Read and abide by the Qt Code of Conduct

          J K 2 Replies Last reply 24 Jan 2020, 20:24
          1
          • C Offline
            C Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on 24 Jan 2020, 20:24 last edited by
            #5

            QWidget::setStyleSheet("") passes an empty string which means the style sheet should be removed. " " is not treated as empty (as it's not empty) but as style sheet.
            btw: You can reset a property in the designer.

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

            1 Reply Last reply
            0
            • K kshegunov
              24 Jan 2020, 20:22

              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.

              J Offline
              J Offline
              JonB
              wrote on 24 Jan 2020, 20:24 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.

              K 1 Reply Last reply 24 Jan 2020, 20:25
              0
              • J Offline
                J Offline
                JonB
                wrote on 24 Jan 2020, 20:25 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.

                C 1 Reply Last reply 24 Jan 2020, 20:26
                0
                • J JonB
                  24 Jan 2020, 20:24

                  @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.

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 24 Jan 2020, 20:25 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
                  • J JonB
                    24 Jan 2020, 20:25

                    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.

                    C Offline
                    C Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on 24 Jan 2020, 20:26 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

                    K 1 Reply Last reply 24 Jan 2020, 20:31
                    0
                    • C Christian Ehrlicher
                      24 Jan 2020, 20:26

                      @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)

                      K Offline
                      K Offline
                      kshegunov
                      Moderators
                      wrote on 24 Jan 2020, 20:31 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
                      • J Offline
                        J Offline
                        JonB
                        wrote on 24 Jan 2020, 20:32 last edited by
                        #11

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

                        1 Reply Last reply
                        0
                        • K kshegunov
                          24 Jan 2020, 20:22

                          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.

                          K Offline
                          K Offline
                          kshegunov
                          Moderators
                          wrote on 24 Jan 2020, 20:33 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

                          J 1 Reply Last reply 24 Jan 2020, 20:34
                          0
                          • K kshegunov
                            24 Jan 2020, 20:33

                            @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.

                            J Offline
                            J Offline
                            JonB
                            wrote on 24 Jan 2020, 20:34 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.

                            K 1 Reply Last reply 24 Jan 2020, 20:35
                            1
                            • J JonB
                              24 Jan 2020, 20:34

                              @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.

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 24 Jan 2020, 20:35 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

                              J 1 Reply Last reply 24 Jan 2020, 20:37
                              0
                              • K kshegunov
                                24 Jan 2020, 20:35

                                @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.

                                J Offline
                                J Offline
                                JonB
                                wrote on 24 Jan 2020, 20:37 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.

                                K 1 Reply Last reply 24 Jan 2020, 20:46
                                0
                                • J JonB
                                  24 Jan 2020, 20:37

                                  @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.

                                  K Offline
                                  K Offline
                                  kshegunov
                                  Moderators
                                  wrote on 24 Jan 2020, 20:46 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

                                  J 1 Reply Last reply 24 Jan 2020, 20:48
                                  0
                                  • K kshegunov
                                    24 Jan 2020, 20:46

                                    @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();
                                    }
                                    
                                    J Offline
                                    J Offline
                                    JonB
                                    wrote on 24 Jan 2020, 20:48 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.

                                    K 1 Reply Last reply 24 Jan 2020, 20:50
                                    0
                                    • J JonB
                                      24 Jan 2020, 20:48

                                      @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.

                                      K Offline
                                      K Offline
                                      kshegunov
                                      Moderators
                                      wrote on 24 Jan 2020, 20:50 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

                                      J 1 Reply Last reply 24 Jan 2020, 20:51
                                      0
                                      • K kshegunov
                                        24 Jan 2020, 20:50

                                        @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)

                                        J Offline
                                        J Offline
                                        JonB
                                        wrote on 24 Jan 2020, 20:51 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
                                        • J Offline
                                          J Offline
                                          JonB
                                          wrote on 24 Jan 2020, 20:53 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

                                          10/24

                                          24 Jan 2020, 20:31

                                          • Login

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