Solved How to color a single row in QTableView
-
@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; } };
-
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.
-
@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?
-
@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!!! -
@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! -
I must insiste:
@SGaist said in How to color a single row in QTableView:
Do the background handling in each of your delegates.
-
@SGaist
I didn't understand how to apply the coloring in the custom delegates. For example on Custom_Two_Delegate which but posted @eyllanesc -
@blackout69 mmm, I assumed that the model you use handled role Qt::BackgroundRole but it seems that this is not true.
- What model do you use?
- 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?
- Is the color fixed or does it also depend on another condition?
-
- I use QSqlRelationalTableModel
- I just want to color a few lines. The coloring depends on the value of a condition. For simplicity I called it mycheck.
- The color is fixed.
-
@blackout69
color all items in that row like the following.
item->setData( Qt::BackgroundRole, QVariant( Qt::red ) );
no delegate is needed. -
@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();
-
@JoeCFD What kind of object is "item"? Remember that not all models support role
Qt::BackgroundRole
. -
@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 -
@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,56double 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;