How to simply change the background colour of a cell inside a TableView



  • I need to change the coulor of some certain cell dependent on value "0" or "1" to the colours "red" or "green" how can I do this?



  • What model are you using?

    P.S.
    Just for future reference, once QTBUG-63766 is solved (and I'm planning to work on it during the xmas period) the solution with QStandardItemModel is trivial



  • @VRonin said in How to simply change the background colour of a cell inside a TableView:

    once QTBUG-63766 is solved

    Can I help you with solving the issue? Although I do not have any clue :D

    Mainly I work with QSqlTableModel or QSqlQueryModel it depends. But in this case QSqlQueryModel makes more sense.



    1. Add this proxy between your model and your view
    2. create a slot
    Q_SLOT void updateBackground(const QModelIndex& srcTopLeft, const QModelIndex& srcBottomRight){
    if(!srcTopLeft.isValid() || !srcBottomRight.isValid())
    return;
    if(srcTopLeft.parent().isValid() || srcBottomRight.parent().isValid())
    return;
    for(int rowIter = srcTopLeft.row();rowIter !=srcBottomRight.row();++rowIter){
    for(int colIter = srcTopLeft.column();colIter !=srcBottomRight.column();++colIter ){
    const QVariant currIdxData = model->index(rowIter,colIter).data(Qt::DisplayRole);
    if(!currIdxData .isValid()){
    proxyModel->setData(proxyModel->index(rowIter,colIter),QVariant(),Qt::BackgroundRole);
    continue;
    }
    if(!currIdxData.canConvert(QMetaType::Int)){
    proxyModel->setData(proxyModel->index(rowIter,colIter),QVariant(),Qt::BackgroundRole);
    continue;
    }
    switch(currIdxData.toInt()){
    case 1:
    proxyModel->setData(proxyModel->index(rowIter,colIter),QBrush(Qt::green),Qt::BackgroundRole);
    break;
    case 0:
    proxyModel->setData(proxyModel->index(rowIter,colIter),QBrush(Qt::red),Qt::BackgroundRole);
    break;
    default:
    proxyModel->setData(proxyModel->index(rowIter,colIter),QVariant(),Qt::BackgroundRole);
    }
    }
    }
    }
    
    1. connect the dataChanged signal from your original model to the newly created slot
    2. optional: if you are working with an editable QSqlTableModel you probably want to change line 29 of the proxy to:
      if(role == Qt::EditRole || index.parent().isValid()) return QIdentityProxyModel::setData(index,value,role);

    Notes

    • The above applies only to flat models (no trees)
    • This will apply the colour to all columns, it's easy to change the slot to ignore columns you don't want to consider


  • @VRonin

    Hi,

    first thks so far for your expanded code example.

    I am trying to understand with small steps so I wrote this code and hoped see something inside the QTableView. But unfortunatelly nothing happens.

       QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel(this);
       proxyModel->setSourceModel(TblModel);
    
          TblModel->setData(proxyModel->index(0,0),QBrush(Qt::red),Qt::BackgroundRole);
    

    TblModel is a QSqlTableModel Object which I generate dircetly inside the constructor.



  • @G4bandit said in How to simply change the background colour of a cell inside a TableView:

    TblModel is a QTableModel

    • There's no such thing as QTableModel in Qt, you have to be a little more specific. If you are talking about QSqlTableModel then the problem is here. It will reject everything other than Qt::EditRole. That's the reason I suggested using ExtraRolesProxyModel in between
    • Are you setting the model on the view? view->setModel(proxyModel);

    P.S.
    It's not a bad idea to wrap setData, insert*, remove* and move* calls in a Q_ASSUME to make sure they actually did what you think they should do



  • @VRonin said in How to simply change the background colour of a cell inside a TableView:

    Are you setting the model on the view? view->setModel(proxyModel);

    I have changed the code to this:

       QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel(this);
       proxyModel->setSourceModel(TblModel);
       ui->TV_DBOut->setModel(proxyModel);
    
          TblModel->setData(proxyModel->index(0,0),QBrush(Qt::red),Qt::BackgroundRole);
    

    But I guess strongly that it is not what you have meant or at all that it is more complex.

    Like you said in your post before:

    1. Add this proxy between your model and your view
      I can not follow you, - I am a bloody newbie.


  • The main question is: what type is TblModel?



  • @VRonin said in How to simply change the background colour of a cell inside a TableView:

    The main question is: what type is TblModel?

    Sry, yes it is of QSqlTableModel.



  • Then TblModel->setData will return false for every role except Qt::EditRole so basically TblModel->setData(proxyModel->index(0,0),QBrush(Qt::red),Qt::BackgroundRole); will do absolutely nothing.

    You need something that handles the other roles that QSqlTableModel ignores. Enter https://pastebin.com/gmNCuUFk



  • @VRonin

    I agree with you TblModel->setData returns false.

    But my main issue still that I am not able to combine all your information/hints/code parts to one working unit.

    1:
    I have created a header file with the content of "https://pastebin.com/gmNCuUFk"
    Do not know what to do with it.

    2:
    and I also tried to run your code posted on
    VRonin 15. Dez. 2017, 10:31

    3:
    And this point
    VRonin: 1.Add this proxy between your model and your view
    Do not know how to



  • @G4bandit said in How to simply change the background colour of a cell inside a TableView:

    Do not know how to

    It's the same as

    QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel(this);
       proxyModel->setSourceModel(TblModel);
       ui->TV_DBOut->setModel(proxyModel);
    

    but instead of QSortFilterProxyModel use ExtraRolesProxyModel



  • I got it!!!

    SUCESS :D

    0_1518084519758_85794cbf-3637-47b4-972a-c6e5d8c48e10-grafik.png

    Thanks a lot



  • If someone ask how to change the color of headers,- here is a helpful link:

    https://stackoverflow.com/questions/32147213/how-to-change-the-background-color-from-the-headerhorizontal-vertical-qtable#32147945

    tview->model()->setHeaderData(0,Qt::Horizontal,QBrush(QColor("red")),Qt::BackgroundRole);
    tview->show();
    
    QApplication::setStyle(QStyleFactory::create("Fusion"));
    

    The last line was on my PC (Win) necessary to get the effect.



  • @G4banditi need to do somo simililar can help me please , i cant understand



  • I now implemented a generic proxy for this, I called it Role Mask Proxy Model. I have an example that changes the background, it uses QStringListModel but it's exactly the same with other base models



  • @VRonin so mucth thanks , wonderfull library, i can do



  • if i use a QSqlRelationalTableModel, Role Mask Proxy Model works????



  • Yes, works on any model



  • @VRonin thanks for your help, now i have a problem, i can not save the data of my QSqlTableModel , i used the example exem_rolemaskeditablesql.cpp i can edit the data but i can not save,



  • If you call addMaskedRole passing either Qt::DisplayRole or Qt::EditRole any change will stay in the proxy and not be passed to the source model.

    You should only mask the roles that you need, in this case Qt::BackgroundRole.

    If it's still not clear, please post us the code using RoleMaskProxyModel and we'll be more specific on the changes to make


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.