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. How to color a single row in QTableView

How to color a single row in QTableView

Scheduled Pinned Locked Moved Solved General and Desktop
19 Posts 4 Posters 6.8k 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.
  • blackout69B Offline
    blackout69B Offline
    blackout69
    wrote on last edited by blackout69
    #1

    Hi everybody,
    I need to color a QTableView row with a different color than the one set as style.

    void MyClass::show(QString filter)
    {
      model = new QSqlRelationalTableModel(this);
      model->setTable(QString("mytable"));
      model->setFilter(filter);
      model->setRelation(2, QSqlRelation("customer", "id_customer", "name"));
      model->setHeaderData(3, Qt::Horizontal, tr("Number"));
      model->setHeaderData(4, Qt::Horizontal, tr("Date"));
      model->setHeaderData(5, Qt::Horizontal, tr("Customer"));
      model->setHeaderData(6, Qt::Horizontal, tr("Total"));
      model->select();
    
      ui->view->setModel(model);
      ui->view->resizeColumnsToContents();
      ui->view->horizontalHeader()->setStretchLastSection(true);
      ui->view->setItemDelegateForColumn(3, new Custom_Num_Delegate(this));  // Center aligned numbers
      ui->view->setItemDelegateForColumn(4, new Custom_Date_Delegate(this));  // Date Format dd/MM/yyyy
      ui->view->setItemDelegateForColumn(5, new Custom_Two_Delegate(this));  //  Total formatted in € 102,25
    }
    

    So far everything works. I have all the data visible on the QTableView.
    Using my Custom Delegates I get all the required formatting. Numbers, Date and Total.
    Using color_row() I wanted to paint only a few red lines.

    void MyClass::color_row()
    {
      for(int row = 0; row < model->rowCount(); row++)
        {
          QSqlRecord record = model->record(i);
    
          if (mycheck)
            {
              for(int column = 0; column < model->columnCount(); column++)
                {
                  model->setData(model->index(row,column),QColor(Qt::red), Qt::BackgroundRole); // Not Work
                }
            }
        }
    }
    

    But it does not work.
    Would anyone know how to give me some advice on how I could solve?
    Thank you in advance
    blackout69

    1 Reply Last reply
    0
    • blackout69B blackout69

      @eyllanesc

      1. I use QSqlRelationalTableModel
      2. I just want to color a few lines. The coloring depends on the value of a condition. For simplicity I called it mycheck.
      3. The color is fixed.
      eyllanescE Offline
      eyllanescE Offline
      eyllanesc
      wrote on last edited by eyllanesc
      #16

      @blackout69 As I suspected: your model only supports role display. A possible solution is that the delegate has the rows that should have the color and then apply it. I have implemented a delegate that should replace all delegates:

      #ifndef DELEGATE_H
      #define DELEGATE_H
      
      #include <QStyledItemDelegate>
      #include <QDateTime>
      #include <QVector>
      
      class Delegate : public QStyledItemDelegate
      {
      public:
          using QStyledItemDelegate::QStyledItemDelegate;
          QVector<int> rows() const
          {
              return m_rows;
          }
          void setRows(const QVector<int> &rows)
          {
              m_rows = rows;
          }
          
      protected:
          void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
              QStyledItemDelegate::initStyleOption(option, index);
              QVariant value = index.data();
              if(index.column() == 3){
                  option->displayAlignment = Qt::AlignCenter;
              }
              else if(index.column() == 4){
                  option->text = option->locale.toString(value.toDateTime(), "dd/MM/yyyy");
              }
              else if(index.column() == 5){
                  option->text = option->locale.toString(value.toDouble(), 'f', 2);
                  option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
              }
              if(m_rows.contains(index.row())){
                  option->backgroundBrush = QBrush(QColor("red"));
              }
          }
      private:
          QVector<int> m_rows;
      };
      
      #endif // DELEGATE_H
      

      Then:

      *.h

      Delegate *m_delegate = nullptr;
      

      *.cpp

      m_delegate = new Delegate;
      ui->view->setItemDelegate(m_delegate);
      

      and:

      m_delegate->setRows({1, 2});
      ui->view->update();
      

      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

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

        Hi,

        Are you doing custom painting in your delegates ?

        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
        • blackout69B Offline
          blackout69B Offline
          blackout69
          wrote on last edited by
          #3

          Hi SGaist,
          Yes. This one my custom delegates:

          class Custom_Two_Delegate : public QItemDelegate
          {
            Q_OBJECT
          
          public:
            Custom_Two_Delegate (QObject *parent);
            void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
          };
          
          Custom_Two_Delegate::Custom_Two_Delegate(QObject *parent) : QItemDelegate(parent)
          {
          
          }
          
          void Custom_Two_Delegate::paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
          {
            double number = index.model()->data(index, Qt::DisplayRole).toDouble();
            QString text = QString("%L1").arg(number,13,'f',2);
            QStyleOptionViewItem myOption = option;
            myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
            drawDisplay(painter, myOption, myOption.rect, text);
            drawFocus(painter, myOption, myOption.rect);
          }
          
          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Then you have to also handle the BackgroundRole as well there. Usually it would be the first thing you paint and then the rest on top of it.

            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
            • blackout69B Offline
              blackout69B Offline
              blackout69
              wrote on last edited by blackout69
              #5

              I tried to create a custom delegate for coloring, but applying the coloring, I lose the formatting.
              I understood that if I apply a custom delegate to the columns, if I apply another one to the rows, it overrides the one applied to the columns

              class Color_Delegate_Red : public QItemDelegate
              {
                Q_OBJECT
              
              public:
                Color_Delegate_Red (QObject *parent);
                void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
                void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
              };
              
              
              Color_Delegate_Red::Color_Delegate_Red(QObject *parent) : QItemDelegate(parent)
              {
              
              }
              
              void Color_Delegate_Red::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
                drawBackground(painter, option, index);
                QItemDelegate::paint(painter, option, index);
              }
              
              void Color_Delegate_Red::drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
                Q_UNUSED(index);
                painter->fillRect(option.rect, QBrush(QColor(Qt::red)));
              }
              
                    if (mycheck)
                            {
                               ......
                              ui->view->setItemDelegateForRow(i, new Color_Delegate_Red(this)); // It works but I lose the formatting 
                    	      }
              
              eyllanescE 1 Reply Last reply
              0
              • blackout69B blackout69

                I tried to create a custom delegate for coloring, but applying the coloring, I lose the formatting.
                I understood that if I apply a custom delegate to the columns, if I apply another one to the rows, it overrides the one applied to the columns

                class Color_Delegate_Red : public QItemDelegate
                {
                  Q_OBJECT
                
                public:
                  Color_Delegate_Red (QObject *parent);
                  void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
                  void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
                };
                
                
                Color_Delegate_Red::Color_Delegate_Red(QObject *parent) : QItemDelegate(parent)
                {
                
                }
                
                void Color_Delegate_Red::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
                {
                  drawBackground(painter, option, index);
                  QItemDelegate::paint(painter, option, index);
                }
                
                void Color_Delegate_Red::drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
                {
                  Q_UNUSED(index);
                  painter->fillRect(option.rect, QBrush(QColor(Qt::red)));
                }
                
                      if (mycheck)
                              {
                                 ......
                                ui->view->setItemDelegateForRow(i, new Color_Delegate_Red(this)); // It works but I lose the formatting 
                      	      }
                
                eyllanescE Offline
                eyllanescE Offline
                eyllanesc
                wrote on last edited by eyllanesc
                #6

                @blackout69 You cannot have 2 delegates for the same item, the last one will replace the previous one. A possible solution is not to modify the paint method but initStyleOption and displayText:

                class Custom_Two_Delegate: public QStyledItemDelegate
                {
                public:
                    using QStyledItemDelegate::QStyledItemDelegate;
                    QString displayText(const QVariant &value, const QLocale &locale) const override{
                        return locale.toString(value.toDouble(), 'f', 2);
                    }
                protected:
                    void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{       
                        QStyledItemDelegate::initStyleOption(option, index);
                        option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
                    }
                
                };
                

                If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

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

                  You should subclass QStyledItemDelegate. That said, you can't stack them on top of each other. Do the background handling in each of your delegates.

                  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
                  • eyllanescE eyllanesc

                    @blackout69 You cannot have 2 delegates for the same item, the last one will replace the previous one. A possible solution is not to modify the paint method but initStyleOption and displayText:

                    class Custom_Two_Delegate: public QStyledItemDelegate
                    {
                    public:
                        using QStyledItemDelegate::QStyledItemDelegate;
                        QString displayText(const QVariant &value, const QLocale &locale) const override{
                            return locale.toString(value.toDouble(), 'f', 2);
                        }
                    protected:
                        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{       
                            QStyledItemDelegate::initStyleOption(option, index);
                            option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
                        }
                    
                    };
                    
                    blackout69B Offline
                    blackout69B Offline
                    blackout69
                    wrote on last edited by
                    #8

                    @eyllanesc
                    Hi eyllanesc
                    As you write, column formatting works.
                    But if I apply the coloring, I lose the formatting.

                    ui->view->setItemDelegateForRow(i, new Color_Delegate_Red(this));
                    

                    How do you paint the entire line that interests me?

                    eyllanescE 1 Reply Last reply
                    0
                    • blackout69B blackout69

                      @eyllanesc
                      Hi eyllanesc
                      As you write, column formatting works.
                      But if I apply the coloring, I lose the formatting.

                      ui->view->setItemDelegateForRow(i, new Color_Delegate_Red(this));
                      

                      How do you paint the entire line that interests me?

                      eyllanescE Offline
                      eyllanescE Offline
                      eyllanesc
                      wrote on last edited by eyllanesc
                      #9

                      @blackout69 It seems that you have not understood my answer, with my solution you should not change anything of your initial logic(model->setData(model->index(row,column),QColor(Qt::red), Qt::BackgroundRole); ) only change the implementation of the delegate that I proposed. Don't use setItemDelegateForRow!!!

                      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                      blackout69B 1 Reply Last reply
                      0
                      • eyllanescE eyllanesc

                        @blackout69 It seems that you have not understood my answer, with my solution you should not change anything of your initial logic(model->setData(model->index(row,column),QColor(Qt::red), Qt::BackgroundRole); ) only change the implementation of the delegate that I proposed. Don't use setItemDelegateForRow!!!

                        blackout69B Offline
                        blackout69B Offline
                        blackout69
                        wrote on last edited by
                        #10

                        @eyllanesc
                        I write:

                        ui->view->setItemDelegateForColumn(5, new Custom_Two_Delegate(this));
                        
                        void MyClass::color_row()
                        {
                          for(int row = 0; row < model->rowCount(); row++)
                            {
                              QSqlRecord record = model->record(i);
                        
                              if (mycheck)
                                {
                                  for(int column = 0; column < model->columnCount(); column++)
                                    {
                                      model->setData(model->index(row,column),QColor(Qt::red), Qt::BackgroundRole);
                                    }
                                }
                        
                            }
                        }
                        

                        Formatting works, but the lines I am interested in are not colored.
                        mycheck is true!

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

                          I must insiste:

                          @SGaist said in How to color a single row in QTableView:

                          Do the background handling in each of your delegates.

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

                          blackout69B 1 Reply Last reply
                          0
                          • SGaistS SGaist

                            I must insiste:

                            @SGaist said in How to color a single row in QTableView:

                            Do the background handling in each of your delegates.

                            blackout69B Offline
                            blackout69B Offline
                            blackout69
                            wrote on last edited by
                            #12

                            @SGaist
                            I didn't understand how to apply the coloring in the custom delegates. For example on Custom_Two_Delegate which but posted @eyllanesc

                            1 Reply Last reply
                            0
                            • blackout69B blackout69

                              @eyllanesc
                              I write:

                              ui->view->setItemDelegateForColumn(5, new Custom_Two_Delegate(this));
                              
                              void MyClass::color_row()
                              {
                                for(int row = 0; row < model->rowCount(); row++)
                                  {
                                    QSqlRecord record = model->record(i);
                              
                                    if (mycheck)
                                      {
                                        for(int column = 0; column < model->columnCount(); column++)
                                          {
                                            model->setData(model->index(row,column),QColor(Qt::red), Qt::BackgroundRole);
                                          }
                                      }
                              
                                  }
                              }
                              

                              Formatting works, but the lines I am interested in are not colored.
                              mycheck is true!

                              eyllanescE Offline
                              eyllanescE Offline
                              eyllanesc
                              wrote on last edited by eyllanesc
                              #13

                              @blackout69 mmm, I assumed that the model you use handled role Qt::BackgroundRole but it seems that this is not true.

                              1. What model do you use?
                              2. do you want to change the color of all the rows? Or just from a particular row? if it is a particular row then what does it depend on?
                              3. Is the color fixed or does it also depend on another condition?

                              If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                              blackout69B 1 Reply Last reply
                              0
                              • eyllanescE eyllanesc

                                @blackout69 mmm, I assumed that the model you use handled role Qt::BackgroundRole but it seems that this is not true.

                                1. What model do you use?
                                2. do you want to change the color of all the rows? Or just from a particular row? if it is a particular row then what does it depend on?
                                3. Is the color fixed or does it also depend on another condition?
                                blackout69B Offline
                                blackout69B Offline
                                blackout69
                                wrote on last edited by
                                #14

                                @eyllanesc

                                1. I use QSqlRelationalTableModel
                                2. I just want to color a few lines. The coloring depends on the value of a condition. For simplicity I called it mycheck.
                                3. The color is fixed.
                                JoeCFDJ eyllanescE 2 Replies Last reply
                                0
                                • blackout69B blackout69

                                  @eyllanesc

                                  1. I use QSqlRelationalTableModel
                                  2. I just want to color a few lines. The coloring depends on the value of a condition. For simplicity I called it mycheck.
                                  3. The color is fixed.
                                  JoeCFDJ Offline
                                  JoeCFDJ Offline
                                  JoeCFD
                                  wrote on last edited by JoeCFD
                                  #15

                                  @blackout69
                                  color all items in that row like the following.
                                  item->setData( Qt::BackgroundRole, QVariant( Qt::red ) );
                                  no delegate is needed.

                                  eyllanescE 1 Reply Last reply
                                  0
                                  • blackout69B blackout69

                                    @eyllanesc

                                    1. I use QSqlRelationalTableModel
                                    2. I just want to color a few lines. The coloring depends on the value of a condition. For simplicity I called it mycheck.
                                    3. The color is fixed.
                                    eyllanescE Offline
                                    eyllanescE Offline
                                    eyllanesc
                                    wrote on last edited by eyllanesc
                                    #16

                                    @blackout69 As I suspected: your model only supports role display. A possible solution is that the delegate has the rows that should have the color and then apply it. I have implemented a delegate that should replace all delegates:

                                    #ifndef DELEGATE_H
                                    #define DELEGATE_H
                                    
                                    #include <QStyledItemDelegate>
                                    #include <QDateTime>
                                    #include <QVector>
                                    
                                    class Delegate : public QStyledItemDelegate
                                    {
                                    public:
                                        using QStyledItemDelegate::QStyledItemDelegate;
                                        QVector<int> rows() const
                                        {
                                            return m_rows;
                                        }
                                        void setRows(const QVector<int> &rows)
                                        {
                                            m_rows = rows;
                                        }
                                        
                                    protected:
                                        void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
                                            QStyledItemDelegate::initStyleOption(option, index);
                                            QVariant value = index.data();
                                            if(index.column() == 3){
                                                option->displayAlignment = Qt::AlignCenter;
                                            }
                                            else if(index.column() == 4){
                                                option->text = option->locale.toString(value.toDateTime(), "dd/MM/yyyy");
                                            }
                                            else if(index.column() == 5){
                                                option->text = option->locale.toString(value.toDouble(), 'f', 2);
                                                option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
                                            }
                                            if(m_rows.contains(index.row())){
                                                option->backgroundBrush = QBrush(QColor("red"));
                                            }
                                        }
                                    private:
                                        QVector<int> m_rows;
                                    };
                                    
                                    #endif // DELEGATE_H
                                    

                                    Then:

                                    *.h

                                    Delegate *m_delegate = nullptr;
                                    

                                    *.cpp

                                    m_delegate = new Delegate;
                                    ui->view->setItemDelegate(m_delegate);
                                    

                                    and:

                                    m_delegate->setRows({1, 2});
                                    ui->view->update();
                                    

                                    If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                                    blackout69B 1 Reply Last reply
                                    1
                                    • JoeCFDJ JoeCFD

                                      @blackout69
                                      color all items in that row like the following.
                                      item->setData( Qt::BackgroundRole, QVariant( Qt::red ) );
                                      no delegate is needed.

                                      eyllanescE Offline
                                      eyllanescE Offline
                                      eyllanesc
                                      wrote on last edited by
                                      #17

                                      @JoeCFD What kind of object is "item"? Remember that not all models support role Qt::BackgroundRole.

                                      If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                                      JoeCFDJ 1 Reply Last reply
                                      0
                                      • eyllanescE eyllanesc

                                        @JoeCFD What kind of object is "item"? Remember that not all models support role Qt::BackgroundRole.

                                        JoeCFDJ Offline
                                        JoeCFDJ Offline
                                        JoeCFD
                                        wrote on last edited by JoeCFD
                                        #18

                                        @eyllanesc
                                        Sorry I am using QTableWidget.

                                        Try this one for all items in one row:
                                        bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);

                                        in case you have issues, check this out.
                                        https://stackoverflow.com/questions/13265992/qabstractitemmodel-setitemdata-returns-false-when-inserting-qtuserrole

                                        1 Reply Last reply
                                        0
                                        • eyllanescE eyllanesc

                                          @blackout69 As I suspected: your model only supports role display. A possible solution is that the delegate has the rows that should have the color and then apply it. I have implemented a delegate that should replace all delegates:

                                          #ifndef DELEGATE_H
                                          #define DELEGATE_H
                                          
                                          #include <QStyledItemDelegate>
                                          #include <QDateTime>
                                          #include <QVector>
                                          
                                          class Delegate : public QStyledItemDelegate
                                          {
                                          public:
                                              using QStyledItemDelegate::QStyledItemDelegate;
                                              QVector<int> rows() const
                                              {
                                                  return m_rows;
                                              }
                                              void setRows(const QVector<int> &rows)
                                              {
                                                  m_rows = rows;
                                              }
                                              
                                          protected:
                                              void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{
                                                  QStyledItemDelegate::initStyleOption(option, index);
                                                  QVariant value = index.data();
                                                  if(index.column() == 3){
                                                      option->displayAlignment = Qt::AlignCenter;
                                                  }
                                                  else if(index.column() == 4){
                                                      option->text = option->locale.toString(value.toDateTime(), "dd/MM/yyyy");
                                                  }
                                                  else if(index.column() == 5){
                                                      option->text = option->locale.toString(value.toDouble(), 'f', 2);
                                                      option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
                                                  }
                                                  if(m_rows.contains(index.row())){
                                                      option->backgroundBrush = QBrush(QColor("red"));
                                                  }
                                              }
                                          private:
                                              QVector<int> m_rows;
                                          };
                                          
                                          #endif // DELEGATE_H
                                          

                                          Then:

                                          *.h

                                          Delegate *m_delegate = nullptr;
                                          

                                          *.cpp

                                          m_delegate = new Delegate;
                                          ui->view->setItemDelegate(m_delegate);
                                          

                                          and:

                                          m_delegate->setRows({1, 2});
                                          ui->view->update();
                                          
                                          blackout69B Offline
                                          blackout69B Offline
                                          blackout69
                                          wrote on last edited by
                                          #19

                                          @eyllanesc
                                          OK well. Now works!
                                          Thanks you have been a great help.

                                          For the sake of completeness, I changed the currency formatting to:
                                          In order to correctly write even the thousands in Euro. Example 1.473,56

                                          double value = index.model()->data(index, Qt::DisplayRole).toDouble();
                                          QString currency = QString("%L1").arg(value,13,'f',2);
                                          option->text = currency;
                                          option->displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
                                          
                                          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