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. Text in QTableView not visible when setting Qt::BackgroundRole
Forum Updated to NodeBB v4.3 + New Features

Text in QTableView not visible when setting Qt::BackgroundRole

Scheduled Pinned Locked Moved Unsolved General and Desktop
24 Posts 4 Posters 2.7k Views 1 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.
  • O Offline
    O Offline
    olowo726
    wrote on last edited by
    #1

    Hi,

    Using Qt 6.3.0

    I'm subclassing QAbstractTableModel and overriding virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; to provide data to a QTableView. Data is provided both for Qt::DisplayRole (returning a QVariant(QString("sometxt")) and Qt::Backgroundrole (returning QVariant(QBrush(QColorConstants::Yellow)))

    For one column which is seldom updated this works fine. But for a different column frequently updated the text isn't show at all, only the background color is painted all over the cell. Updates of the malfunctioning column are triggered with

    QVector<int> roles;
    roles.push_back(Qt::DisplayRole);
    Q_EMIT dataChanged(topLeftValue, bottomRightValue, roles);
    

    topLeftValue and bottorRightValue of course being indexes. Note Qt::DisplayRole, not Qt::Backgroundrole.

    Why isn't the text shown at all, only the background, when dataChanged() is frequently emitted? I can add that if data returns QVariant() for the background role it works fine (i.e. the view displays black text on white background) also for frequently updated columns).

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      How often is "more frequently" ?
      Are you also changing other roles ?
      Do you have a different logic for the column that fails ?
      Do you have a custom view ?

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

      1 Reply Last reply
      0
      • O Offline
        O Offline
        olowo726
        wrote on last edited by
        #3

        "more frequent" - 50ms timer
        "Are you also changing other roles ?" Only working with Display and Background
        "Do you have a different logic for the column that fails ?" Don't understand the question - it's a different logic because it doesn't show the same data
        "Do you have a custom view ?" - Nope, pure QTableView

        1 Reply Last reply
        0
        • O Offline
          O Offline
          olowo726
          wrote on last edited by
          #4

          I shall add that I think this has worked in earlier Qt versions since we have an old feature in our app which also frequently modifies background role. I know this feature has been working before but is now broken.

          1 Reply Last reply
          0
          • O Offline
            O Offline
            olowo726
            wrote on last edited by
            #5

            Actually I did have a delegate according to https://stackoverflow.com/questions/64198197/how-to-prevent-too-aggressive-text-elide-in-qtableview.

            This delegate is obviously the culprit since disabling it solves the issue. But alas I need the elide....

            I guess that

            QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
            

            Overwrites the text when there is a background color. Moving the drawText to below drawControl resulted in no text whatsoever regardless of background color.

            So, how can I get both proper elide and background color in a table cell?

            1 Reply Last reply
            0
            • C Offline
              C Offline
              ChrisW67
              wrote on last edited by
              #6

              The delegate on the SO post sets the opt.text to an empty string before calling drawControl() which dutifully renders a blanks cell. If drawControl() does not fill a background (because the background role is null) then the already painted text is left untouched. In short, I think that delegate worked by accident not design.

              Something like this is what I would have tried:

              void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                                    const QModelIndex &index) const
               {
                   if (!index.isValid())
                       return;
              
                   QStyleOptionViewItem opt = option;
                   initStyleOption(&opt, index);
                  
              // elide and store the text if needed.
                  opt.text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight, opt.rect.width() ) );
              // make sure the style does not try to elide the elided text
                  opt.textElideMode = Qt::ElideNone;
                   QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
               }
              
              1 Reply Last reply
              0
              • O Offline
                O Offline
                olowo726
                wrote on last edited by olowo726
                #7

                I tried this suggestion. It works fine - for negative numbers only! For positive numbers opt.text is elided properly, i.e. after call to elideText it contains the properly elided text string but that's displayed is "0...." with really a lot of blank space available in the cell. I guess that's related to https://bugreports.qt.io/browse/QTBUG-87178

                So, paint the background in the elide?

                1 Reply Last reply
                0
                • O Offline
                  O Offline
                  olowo726
                  wrote on last edited by
                  #8
                  This post is deleted!
                  1 Reply Last reply
                  0
                  • C Offline
                    C Offline
                    ChrisW67
                    wrote on last edited by
                    #9

                    What is interesting is that this behaviour is only if the value looks like a number (even it is QVariant(String)) and correct otherwise:

                    Screenshot_20220715_172718.png

                    Have not got a good workaround yet.

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      You should check opt.rect.width() if it's different for your cells.

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

                      O 1 Reply Last reply
                      0
                      • Christian EhrlicherC Christian Ehrlicher

                        You should check opt.rect.width() if it's different for your cells.

                        O Offline
                        O Offline
                        olowo726
                        wrote on last edited by
                        #11

                        @Christian-Ehrlicher It's the same for both working and non-working strings in my case.

                        1 Reply Last reply
                        0
                        • O Offline
                          O Offline
                          olowo726
                          wrote on last edited by
                          #12

                          I think that this thread has became a bit messy due to me not realizing from start that I had a delegate. To summarize:
                          I need a solution which fulfills

                          1. Proper elide
                          2. Possible to set background color by emitting dataChanged() from the model in a method called by a timer at ~50ms
                          3. Possible to edit value as normal.

                          QTBUG: https://bugreports.qt.io/browse/QTBUG-87178
                          Solution which fulfills req 1 but not 2 and 3: https://stackoverflow.com/questions/64198197/how-to-prevent-too-aggressive-text-elide-in-qtableview

                          Start a new thread which makes this more clear for anyone else looking for a solution to this problem?

                          Christian EhrlicherC 1 Reply Last reply
                          0
                          • O olowo726

                            I think that this thread has became a bit messy due to me not realizing from start that I had a delegate. To summarize:
                            I need a solution which fulfills

                            1. Proper elide
                            2. Possible to set background color by emitting dataChanged() from the model in a method called by a timer at ~50ms
                            3. Possible to edit value as normal.

                            QTBUG: https://bugreports.qt.io/browse/QTBUG-87178
                            Solution which fulfills req 1 but not 2 and 3: https://stackoverflow.com/questions/64198197/how-to-prevent-too-aggressive-text-elide-in-qtableview

                            Start a new thread which makes this more clear for anyone else looking for a solution to this problem?

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

                            @olowo726 said in Text in QTableView not visible when setting Qt::BackgroundRole:

                            Possible to set background color by emitting dataChanged() from the model in a method called by a timer at ~50ms

                            As I saidf in the bug report - such update rates are useless / stupid for a gui showing numbers...

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

                            O 1 Reply Last reply
                            0
                            • Christian EhrlicherC Christian Ehrlicher

                              @olowo726 said in Text in QTableView not visible when setting Qt::BackgroundRole:

                              Possible to set background color by emitting dataChanged() from the model in a method called by a timer at ~50ms

                              As I saidf in the bug report - such update rates are useless / stupid for a gui showing numbers...

                              O Offline
                              O Offline
                              olowo726
                              wrote on last edited by
                              #14

                              @Christian-Ehrlicher said in Text in QTableView not visible when setting Qt::BackgroundRole:

                              As I saidf in the bug report - such update rates are useless / stupid for a gui showing numbers...

                              In this case it isn't about the number, it's about the background color. The user will very quickly perceive when the color box moves on the screen and if that's a lot slower than the physical machine which the user can observe simultaneously then the user experience will be suffering. Humans are quite sensitive to time lag in user experience. One could go to 100ms but not 1s.

                              Anyway, let's say 1s is possible, then the elide delegate from the SO post still prevents the user to edit the value because it repaints the control with the existing value from the model, not the digits the user has entered this far, when a dataChanged() for background color is emitted. Can the delegate detect that user editing is in progress?

                              1 Reply Last reply
                              0
                              • C Offline
                                C Offline
                                ChrisW67
                                wrote on last edited by
                                #15

                                If user editing of a value is in progress then the display within the cell's region of the view is driven by the editor widget that is created when the cell switch to edit mode. You are going to need to post a complete program that demonstrates the new problem.

                                O 1 Reply Last reply
                                2
                                • C ChrisW67

                                  If user editing of a value is in progress then the display within the cell's region of the view is driven by the editor widget that is created when the cell switch to edit mode. You are going to need to post a complete program that demonstrates the new problem.

                                  O Offline
                                  O Offline
                                  olowo726
                                  wrote on last edited by
                                  #16

                                  @ChrisW67 Here you are: https://udokaelectronics.com/files/untitled.zip

                                  Comment out

                                  ui->tableView->setItemDelegate(elideDelegate);
                                  

                                  To see the result with and without the delegate.

                                  Without the elide delegate all works fine except the elide. With the elide delegate the background overwrites the text and the existing text is continuously redrawn during editing of cell content.

                                  1 Reply Last reply
                                  0
                                  • SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by SGaist
                                    #17

                                    Why are you drawing the text and then on top of it call the style's drawControl method with no text ?

                                    What would make more sense is to change the text and elide value of the option and pass the modified option to the base class paint method.

                                    Also, why nuke the options object you just got by calling init on it ?

                                    Note I have just read the delegate's code you provided.

                                    [edit: options must be updated as done, see base class implementation SGaist]

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

                                    1 Reply Last reply
                                    0
                                    • O Offline
                                      O Offline
                                      olowo726
                                      wrote on last edited by olowo726
                                      #18

                                      I have tried the straightforward implementation

                                      void ElideDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                                                                const QModelIndex &index) const {
                                        if (!index.isValid()) {
                                          return;
                                        }
                                      
                                        QStyleOptionViewItem opt = option;
                                        initStyleOption(&opt, index);
                                      
                                        opt.text= opt.fontMetrics.elidedText(opt.text, Qt::ElideRight, opt.rect.width());
                                        opt.textElideMode = Qt::ElideNone;
                                      
                                        QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
                                      }
                                      

                                      opt.text is for some reason blank until initStyleOption(&opt, index); returns. Hence "nuking" opt by initStyleOption(&opt, index); is necessary.

                                      With the code above and string "1.234567890" the string gets properly elided by opt.fontMetrics.elidedText to for example "1.2345..." but the view still shows "1....". Note that this problem is only present for positive numbers. It works fine without the delegate for negative numbers.

                                      Substituting QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter); with QStyledItemDelegate::paint(painter, opt, index); doesn't help. Perhaps related to that one needs to call initStyleOption() to get the actual text so perhaps QStyledItemDelegate::paint does the same and hence discards all changes to the text.

                                      1 Reply Last reply
                                      0
                                      • O Offline
                                        O Offline
                                        olowo726
                                        wrote on last edited by
                                        #19

                                        I just discovered by exploratory testing that giving opt.fondMetrics.elidedText some margin seems to do the trick, i.e. replace opt.text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight,opt.rect.width() ); with opt.text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight,opt.rect.width() - 10);.

                                        That gives me both background color and elided text. No idea of how portable it is though.

                                        But it doesn't solve the issue with text being overwritten when the model emits dataChanged() with role Backgroundrole when user edit is in progress. Is is possible to somehow detect when user edit is in progress? Override QAbstractItemView:edit() to detect start of user edit, but how detect when user edit is finished? Override closeEditor() and assume there is only one edit active at once?

                                        1 Reply Last reply
                                        0
                                        • SGaistS Offline
                                          SGaistS Offline
                                          SGaist
                                          Lifetime Qt Champion
                                          wrote on last edited by
                                          #20

                                          You were right about the use of initStyleOption, I had it at the wrong place.

                                          Can you explain the use case of a user editable value that can be replaced under the hood programmatically while being edited ?

                                          It looks like it should rather be a independent way to input data to avoid collision or an "edit mode" where the other updates are disabled.

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

                                          O 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