How to color a row of qSqlQueryModel where data of cell is smth
-
class ColorDelegate: public QItemDelegate { Q_OBJECT public: QSet<QString> alarmsSet; ColorDelegate(QObject *parent = 0) : QItemDelegate(parent) {} public: virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { drawBackground(painter, option, index); QItemDelegate::paint(painter, option, index); }; protected: virtual void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { //qDebug()<<alarmsSet; // foreach (const QString &value, alarmsSet){ if (index.data() ==damage) { painter->fillRect(option.rect, QBrush(Qt::yellow, Qt::SolidPattern)); } // } } private: QString damage = "Damage"; signals: private slots: void alarms(QSet<QString> set){ alarmsSet= set; } };When I set this class as ItemDelegate to my qTableView I color a cell with "Damage" data. And this is the result.
My aim is to color a row with a specific message. I have a slot that provides all the messages that need to be colored but when I use them in drawBackground my QSet is empty.How can I do this, why is my QSet empty in drawBackground and is it possible to do it so?
-
class ColorDelegate: public QItemDelegate { Q_OBJECT public: QSet<QString> alarmsSet; ColorDelegate(QObject *parent = 0) : QItemDelegate(parent) {} public: virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { drawBackground(painter, option, index); QItemDelegate::paint(painter, option, index); }; protected: virtual void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { //qDebug()<<alarmsSet; // foreach (const QString &value, alarmsSet){ if (index.data() ==damage) { painter->fillRect(option.rect, QBrush(Qt::yellow, Qt::SolidPattern)); } // } } private: QString damage = "Damage"; signals: private slots: void alarms(QSet<QString> set){ alarmsSet= set; } };When I set this class as ItemDelegate to my qTableView I color a cell with "Damage" data. And this is the result.
My aim is to color a row with a specific message. I have a slot that provides all the messages that need to be colored but when I use them in drawBackground my QSet is empty.How can I do this, why is my QSet empty in drawBackground and is it possible to do it so?
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
but when I use them in drawBackground my QSet is empty
why is my QSet empty in drawBackground
Hello and welcome.
The code you show has a
QSet<QString> alarmsSetmember variable, and a slot which assigns this set to a set passed as a parameter to it. Nobody can tell when you call that from the code you show, so nobody can tell you why it is empty.if (index.data() ==damage)What is this
damagevariable, which you can compare against the value at an index in the model? Note that this is only looking at one cell. If you want all cells in a row to be drawn a certain way based on the content/value of one cell, you will have to get the other cells to look in that one cell in the row when it is their turn to be drawn in order to dictate how they themselves are to be drawn.It might be that using some role value on al cells would be a good way to store how their background is to be shown.
-
The slot executes correctly and transfers the data
and this is my damage variable.private: QString damage = "Damage"; -
The slot executes correctly and transfers the data
and this is my damage variable.private: QString damage = "Damage";@SimonaBolgradova Instead of a delegate you could use a proxy model.
here is a simple python exampleclass MyModel(QIdentityProxyModel): def data(self, proxyIndex: Union[QModelIndex, QPersistentModelIndex], role: int = ...) -> Any: if Qt.BackgroundRole == role: v = super().data(proxyIndex, Qt.DisplayRole) if 'Damage' in v: return QColor('yellow') return super().data(proxyIndex, role) -
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
but when I use them in drawBackground my QSet is empty
why is my QSet empty in drawBackground
Hello and welcome.
The code you show has a
QSet<QString> alarmsSetmember variable, and a slot which assigns this set to a set passed as a parameter to it. Nobody can tell when you call that from the code you show, so nobody can tell you why it is empty.if (index.data() ==damage)What is this
damagevariable, which you can compare against the value at an index in the model? Note that this is only looking at one cell. If you want all cells in a row to be drawn a certain way based on the content/value of one cell, you will have to get the other cells to look in that one cell in the row when it is their turn to be drawn in order to dictate how they themselves are to be drawn.It might be that using some role value on al cells would be a good way to store how their background is to be shown.
-
@SimonaBolgradova
So you do appear to set the value and your picture shows that you are indeed coloring the "Damage" cell yellow. In which case it seems to behaving as per your code, so what is your question?Meanwhile you might prefer to try @Gojir4's suggestion of doing the background coloring from the
data()method instead of a delegate. But I'm not sure that has anything to do with whatever your actual question is. -
@SimonaBolgradova
So you do appear to set the value and your picture shows that you are indeed coloring the "Damage" cell yellow. In which case it seems to behaving as per your code, so what is your question?Meanwhile you might prefer to try @Gojir4's suggestion of doing the background coloring from the
data()method instead of a delegate. But I'm not sure that has anything to do with whatever your actual question is.@JonB said in How to color a row of qSqlQueryModel where data of cell is smth:
So you do appear to set the value and your picture shows that you are indeed coloring the "Damage" cell yellow. In which case it seems to behaving as per your code, so what is your question?
Meanwhile you might prefer to try @Gojir4's suggestion of doing the background coloring from the data() method instead of a delegate. But I'm not sure that has anything to do with whatever your actual question is.My question was why when I use alarmsSet in drawnBackgroung is empty set and how to color the whole row.
And could you show me some simple example with data()
-
You are overcomplicating things, it's super straightforward:
class ColorDelegate: public QStyledItemDelegate{ Q_OBJECT public: using QStyledItemDelegate::QStyledItemDelegate; const QSet<QString>& alarms() const {return m_alarms;} void setAlarms(const QSet<QString>& alm) {m_alarms=alm;} protected: void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{ QStyledItemDelegate::initStyleOption(option,index); if(m_alarms.contains(index.data().toString()) option->backgroundBrush = QBrush(Qt::yellow, Qt::SolidPattern); } private: QSet<QString> m_alarms; };how to color the whole row.
Instead of
index.data().toString()useindex.sibling(index.row(),ColumnWithAlarms).data().toString()P.S.
Thedata()solution is perfectly valid, I disagree with it only on a philosophical level (philosophy has hardly any place in programming anyway) as the color isn't data, it's a way to paint existing data. At the end of the day, use the solution you find easier -
@JonB said in How to color a row of qSqlQueryModel where data of cell is smth:
So you do appear to set the value and your picture shows that you are indeed coloring the "Damage" cell yellow. In which case it seems to behaving as per your code, so what is your question?
Meanwhile you might prefer to try @Gojir4's suggestion of doing the background coloring from the data() method instead of a delegate. But I'm not sure that has anything to do with whatever your actual question is.My question was why when I use alarmsSet in drawnBackgroung is empty set and how to color the whole row.
And could you show me some simple example with data()
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
and how to color the whole row.
I already answered this:
If you want all cells in a row to be drawn a certain way based on the content/value of one cell, you will have to get the other cells to look in that one cell in the row when it is their turn to be drawn in order to dictate how they themselves are to be drawn.
But you do not seem to have acknowledged this.
Note that if only the value in the Message column changes you want that to affect the color of all the other cells in that row. It is your responsibility to tell the view that those other cells have changed and need their color to be redrawn (else it will only do the Message column in the row), e.g. via a suitable
dataChanged()signal. Although @VRonin mentionssibling()in his code he does not seem to have pointed out that you will need to cause the redraw in those columns? -
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
and how to color the whole row.
I already answered this:
If you want all cells in a row to be drawn a certain way based on the content/value of one cell, you will have to get the other cells to look in that one cell in the row when it is their turn to be drawn in order to dictate how they themselves are to be drawn.
But you do not seem to have acknowledged this.
Note that if only the value in the Message column changes you want that to affect the color of all the other cells in that row. It is your responsibility to tell the view that those other cells have changed and need their color to be redrawn (else it will only do the Message column in the row), e.g. via a suitable
dataChanged()signal. Although @VRonin mentionssibling()in his code he does not seem to have pointed out that you will need to cause the redraw in those columns?@JonB said in How to color a row of qSqlQueryModel where data of cell is smth:
does not seem to have pointed out that you will need to cause the redraw in those columns?
Excellent spot as always!
connect(model,QAbstractItemModel::dataChanged,view,[=](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles){ if(!roles.isEmpty() && !roles.contains(Qt::DisplayRole)) return; if(ColumnWithAlarms < topLeft.column() || ColumnWithAlarms > bottomRight.column()) return; view->update(); }); -
You are overcomplicating things, it's super straightforward:
class ColorDelegate: public QStyledItemDelegate{ Q_OBJECT public: using QStyledItemDelegate::QStyledItemDelegate; const QSet<QString>& alarms() const {return m_alarms;} void setAlarms(const QSet<QString>& alm) {m_alarms=alm;} protected: void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override{ QStyledItemDelegate::initStyleOption(option,index); if(m_alarms.contains(index.data().toString()) option->backgroundBrush = QBrush(Qt::yellow, Qt::SolidPattern); } private: QSet<QString> m_alarms; };how to color the whole row.
Instead of
index.data().toString()useindex.sibling(index.row(),ColumnWithAlarms).data().toString()P.S.
Thedata()solution is perfectly valid, I disagree with it only on a philosophical level (philosophy has hardly any place in programming anyway) as the color isn't data, it's a way to paint existing data. At the end of the day, use the solution you find easier@VRonin how to get alarms from my slot
private slots: void alarms(QSet<QString> set){ setAlarms(set); }Is it smth like that?
and why I have this error

-
@VRonin how to get alarms from my slot
private slots: void alarms(QSet<QString> set){ setAlarms(set); }Is it smth like that?
and why I have this error

@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
how to get alarms from my slot
Don't know what this means.
and why I have this error
Start with how can the method be
constif it altersm_alarms? [ @VRonin ?? :) ] -
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
how to get alarms from my slot
Don't know what this means.
and why I have this error
Start with how can the method be
constif it altersm_alarms? [ @VRonin ?? :) ]@JonB said in How to color a row of qSqlQueryModel where data of cell is smth:
Start with how can the method be const if it alters m_alarms? [ @VRonin ?? :) ]
Yep, corrected.
P.S.
In most use cases you don't need a slot. Using Qt5 connections you can connect directly to thesetAlarmsmethod -
m_alarms keeps to be empty :(
I connected like that in another class named Controllerconnect( s, &SQLQueries::alarms, d, &ColorDelegate::setAlarms );Alarms signal will be emitted when I triggered action on and m_alarms get some values but then in initStyleOption m_alarms is empty.

-
void MainWindow::setTable(QSqlQueryModel * model) { ui->tableView->setModel( model ); ui->tableView->setItemDelegate(new ColorDelegate(ui->tableView)); ui->tableView->resizeColumnsToContents(); } -
void MainWindow::setTable(QSqlQueryModel * model) { ui->tableView->setModel( model ); ui->tableView->setItemDelegate(new ColorDelegate(ui->tableView)); ui->tableView->resizeColumnsToContents(); }@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
ui->tableView->setItemDelegate(new ColorDelegate(ui->tableView));
Fire and forget pointer. The delegate you are connecting is not the one used by the view then. what is
dind, &ColorDelegate::setAlarms?It should be something like:
auto alarmDelegate = new ColorDelegate(ui->tableView); ui->tableView->setItemDelegate(alarmDelegate); connect(s, &SQLQueries::alarms, alarmDelegate, &ColorDelegate::setAlarms); -
@SimonaBolgradova said in How to color a row of qSqlQueryModel where data of cell is smth:
ui->tableView->setItemDelegate(new ColorDelegate(ui->tableView));
Fire and forget pointer. The delegate you are connecting is not the one used by the view then. what is
dind, &ColorDelegate::setAlarms?It should be something like:
auto alarmDelegate = new ColorDelegate(ui->tableView); ui->tableView->setItemDelegate(alarmDelegate); connect(s, &SQLQueries::alarms, alarmDelegate, &ColorDelegate::setAlarms);Fire and forget pointer. The delegate you are connecting is not the one used by the view then. what is
dind, &ColorDelegate::setAlarms?in controller.h
private: ColorDelegate * d = new ColorDelegate();It should be something like:
auto alarmDelegate = new ColorDelegate(ui->tableView); ui->tableView->setItemDelegate(alarmDelegate); connect(s, &SQLQueries::alarms, alarmDelegate, &ColorDelegate::setAlarms);this doesn't work and all fields are empty in my QTableView
-
Fire and forget pointer. The delegate you are connecting is not the one used by the view then. what is
dind, &ColorDelegate::setAlarms?in controller.h
private: ColorDelegate * d = new ColorDelegate();It should be something like:
auto alarmDelegate = new ColorDelegate(ui->tableView); ui->tableView->setItemDelegate(alarmDelegate); connect(s, &SQLQueries::alarms, alarmDelegate, &ColorDelegate::setAlarms);this doesn't work and all fields are empty in my QTableView
@SimonaBolgradova maybe the problem is that my connection was created in the Controller class. There I create an instance of ColorDelegate and m_alarms is still empty. But how could I connect two classes into another without creating an instance?
-
What you are doing at the moment is
int a=0; int b=3;and asking whyais 0 and not 3. They are the same type (int) but 2 different objects. You need to callsetAlarmson the same object as the one used in the view.But how could I connect two classes into another without creating an instance?
This question is asked weekly if not daily in this forum just search for "connecting to class". The short answer is that you should structure your app as a tree where the leaves are connected by the branches
