Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Qt Academy Launch in California!

    Unsolved QSpinBox cannot set its QLineEdit background colour under Linux

    General and Desktop
    3
    15
    825
    Loading More Posts
    • 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.
    • P
      Phil K last edited by

      I'm amending my code snippet above so that it works properly with scroll areas and tree views. The row of the QModelIndex won't tell you the row needed for accurate alternate coloring. i.e. you need the row relative to the top of the scroll area and, for item views, the data above you might also be in various states of expand/collapse.

      In digging through the Qt code, I notice that the QStyleOptionViewItem delivered to delegate's createEditor does not carry the feature QStyleOptionViewItem::Alternate. That bit is added by the tree view in drawRow. This is too bad since that bit could directly tell us whether or not we're on an alternate row. That bit is sent into the delegate's paint function however, so you could play with it there.

      QWidget *SpinboxDelegate::createEditor(
              QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
      {
          QSpinBox *editor = new QSpinBox(parent);
          editor->setAlignment(Qt::AlignRight);
          editor->setAutoFillBackground(true);
          const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(option.widget);
          if (view) {
              // determine row that the index is sitting on relative to top of scroll area
              const QRect rect = view->visualRect(index);
              const int pos = view->verticalScrollBar()->value();
              const int row = pos + (rect.top() / rect.height());
              // hack to grab protected QLineEdit from QSpinBox parent
              auto line_editors = editor->findChildren<QLineEdit*>();
              QLineEdit *line_editor = !line_editors.empty() ? line_editors.front() : nullptr;
              if (line_editor && index.isValid()) {
                  // line editor background color set to current row background color
                  const QPalette app_palette = qApp->palette();
                  QPalette palette = line_editor->palette();
                  palette.setColor(QPalette::Base, row % 2 ?
                                       app_palette.color(QPalette::AlternateBase) :
                                       app_palette.color(QPalette::Base));
                  line_editor->setPalette(palette);
              }
          }
          editor->setFrame(false);
          editor->setMinimum(-100000);
          editor->setMaximum(100000);
          return editor;
      
      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi,

        I currently wonder whether it's something that should be available there. Did you check the bug report system to see if there's something related ? If not, you could open a feature request.

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

        P JonB 2 Replies Last reply Reply Quote 0
        • P
          Phil K @SGaist last edited by

          @SGaist In the context of delegates, the editor is created by the QAbstractItemView on this line of code and if you trace it back, you can see that openEditor is not adding the option features that drawRow adds in the QTreeView derivation for the paint calls. Not sure it would be easy to add that style feature on that abstract class. Perhaps.

          1 Reply Last reply Reply Quote 0
          • JonB
            JonB @SGaist last edited by JonB

            @SGaist
            Are you addressing this to @Phil-K or to myself?

            I wrote earlier that I reported this bug as https://bugreports.qt.io/browse/QTBUG-83961 9 months ago, but haven't had any takers :) [Other than 2 non-expert replies, to which I responded as both were wrong!]

            I can't say for @Phil-K's response now. But, at least in my non-edit case, one should not need to write some set of code. There is just something fundamentally wrong in Qt's internal code for handling the QLineEdit part of a QSpinBox, at least so far as my coloring via stylesheet is concerned.

            1 Reply Last reply Reply Quote 0
            • SGaist
              SGaist Lifetime Qt Champion last edited by

              At @Phil-K but somehow I managed to miss the link to the existing report... vertical scrolling is sometimes treacherous.

              The current answers are indeed inadequate.

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

              P 1 Reply Last reply Reply Quote 0
              • P
                Phil K @SGaist last edited by Phil K

                I necro'd the thread and went off on a tangent. Scrolling is not relevant to the original problem. The style painter is painting that QSpinBox with a call from paintEvent to drawComplexControl so you would need to trace the drawing code through the style machinery to see what's happening. As a workaround you can set the stylesheet for the QSpinBox instead of the editor, but you'll have to adjust the buttons using the QSpinBox::up-button/::down-button subcontrol selectors. Too bad there isn't a subcontrol css selector for the QLineEdit itself. That would help. Also, I note that the css selectors for children (#qt_spinbox_lineedit or QSpinBox > QLineEdit) indeed don't seem to work in this context, so the drawing code is probably using the spinbox style settings and ignoring the rest.

                1 Reply Last reply Reply Quote 0
                • P
                  Phil K last edited by

                  @JonB Here's a fast workaround that you may like. Give the parent widget an object name and set its stylesheet using the #id selector. That will prevent the problematic propagation to the QLineEdit of the QSpinBox. Cheers.

                  #include <QApplication>
                  #include <QLineEdit>
                  #include <QSpinBox>
                  #include <QVBoxLayout>
                  #include <QWidget>
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                      QWidget w;
                      QVBoxLayout layout;
                      w.setGeometry(100, 100, 200, 200);
                      w.setLayout(&layout);
                      // Use #id selector to prevent propagation
                      w.setObjectName("my_widget");
                      w.setStyleSheet("#my_widget {background-color: yellow; color: green;}");
                  
                      QLineEdit *lineEdit = new QLineEdit;
                      layout.addWidget(lineEdit);
                      lineEdit->setText("50");
                      lineEdit->setStyleSheet("background-color: cyan; color: red;");
                  
                      QSpinBox *spinBox = new QSpinBox;
                      layout.addWidget(spinBox);
                      QLineEdit *spinLineEdit = spinBox->findChild<QLineEdit *>();
                      spinBox->setMaximum(100);
                      spinBox->setMinimum(-100);
                      spinBox->setValue(50);
                      spinLineEdit->setStyleSheet("background-color: blue; color: red;");
                  
                      w.show();
                      return a.exec();
                  }
                  
                  JonB 1 Reply Last reply Reply Quote 1
                  • JonB
                    JonB @Phil K last edited by JonB

                    @Phil-K
                    Hi Phil. Yes, I realize what you are doing here, but unfortunately this does not do the job correctly enough for my requirements.

                    Firstly, the result of yours is:
                    Screenshot from 2021-01-26 09-55-56.png

                    Compare that to the correct one I show earlier above. Not surprisingly, while the line edit itself is now correct colors, the spinbox "furniture" around it has now lost the desired background yellow of the whole form and is shown in the default "grey".

                    Secondly, I had to cut mine down to a minimal example. In practice I have a top-level background-colored widget, whose color I want inherited everywhere except when overridden, then I have a potentially-unknown hierarchy of further sub-widgets, and at the bottom I have a QSpinBox. Colored-widget -> widget -> widget -> ... -> spinbox. And I have loads of these QSpinBoxes. Setting the color on the top-level widget by id will limit it to that widget only, and there is no chance of picking out all the direct parent widgets of the child spinboxes for application of some distant, top-level color which may have been specified.

                    The problem, it seems to me, must be addressed on the QSpinBox itself, not higher up the hierarchy. And the issue is that somewhere in the Qt code there is some "unusal" handling of the QSpinBox::lineEdit() such that you cannot get it to respect its own stylesheet rule iff some ancestor does specify colors. Tackling this somehow at a "top-level" widget cannot be the solution. I refer you again to my example which shows that a standalone QLineEdit does behave correctly in this situation, while the QLineEdit internal to a QSpinBox does not in the same situation. This is a QSpinBox-alone issue. Which is what I need resolved or at least explained!

                    P 1 Reply Last reply Reply Quote 0
                    • P
                      Phil K @JonB last edited by Phil K

                      @JonB Well my suggestion is to read the Qt code and find the exact areas where the problem exists and propose a patch on your bug report. I had an old boss many years ago who said "Don't come to me with a problem. Come to me with a problem, three solutions and a recommendation." Good luck.

                      JonB 1 Reply Last reply Reply Quote 0
                      • JonB
                        JonB @Phil K last edited by

                        @Phil-K
                        Yes the solution to any question Qt can be read the code and find out for yourself. Difficult when I have never compiled Qt, can't step through the code, and am looking to try to find out why some stylesheet rule is or is not overridden by some inheritance elsewhere, which I'm pretty sure will be convoluted/a minefield to work out. Which is why I raised it as a bug at bugreports, in the hope that someone who maintains that code might post an answer. But not. Thank you for your interest.

                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post